Welche Ansatz meinst du, ich verfolge mal den mit Thread weiter
public class Form1 .....
private ThreadClass myThreadClass;
private void miListepruefen_Click(object sender, System.EventArgs e)
{
Thread t = new Thread(new ThreadStart(checkList));
t.Start();
}
private void checkList()
{
myThreadClass = new ThreadClass((string)lvURLs.ToArray);
lvInvalidUrl = myThreadClass.InvalidatetURL;
lvValidUlrs = myThreadClass.ValidatetURL;
}
}
public class ThreadClass
{
private ArrayList invalURL = new ArrayList();
private ArrayList valURL = new ArrayList();
private ThreadClass(string[] args)
{
AccountChecker urlToTest;
foreach(string url in args)
{
urlToTest = new URLChecker();
if (urlToTest.checkURL(lviTemp.Text,lviTemp.SubItems [0].Text,lviTemp.SubItems[1].Text) == false)
{
invalURL.item.Add(url);
}
else
{
valURL.item.Add(url);
}
}
}
public ArrayList InvalidatetURL
{
get
{
return invalURL;
}
}
public ArrayList ValidatetURL
{
get
{
return valURL;
}
}
Der einzige Unterschied von deinem Code zu meinen Code (wo es ge funtzt hat) ist das ich diese Methoden in eine neue Klasse gepackt habe. Und in der Start Methode des Thread eine neue Instanz geöffnet habe.
Da durch müssen die beiden Thread nicht auf ein und die selbe Variable zurück greifen.
Über gebe der neuen Klasse am besten ein string Array, da wird neuer Speicherplatz reserviert. Bei dem ArrayList wird nur eine Referenze (Pointer) übergeben.
--- bin solangsam mit meinen Latein am Ende 🤔 🙁
Ansonsten muss der Benutzer solange warten bis die URL gescheckt sind. Un ihm eine schöne Progressbar vor die Augen setzen
oh ja jetzt sorry mein Fehler
du musst den Thread noch in den Hintergrund schieben. Das geht so ...
...
Thread t = new Thread(new ThreadStart(checkList));
t.Background = true;
t.Start();
...
Also wenn ich die MSDN richtig verstehe, dann musst du nur die Werte in der richtigen Reihnfolge hinzufügen.
Aus der MSDN
Der OLE DB-.NET-Provider unterstützt keine benannten Parameter für die Übergabe von Parametern an eine SQL-Anweisung oder gespeicherte Prozedur, die von OleDbCommand aufgerufen wird, wenn CommandType auf Text festgelegt ist. In diesem Fall muss das Fragezeichen (?) als Platzhalter verwendet werden. Beispiel:
SELECT * FROM Customers WHERE CustomerID = ?
Die Reihenfolge, in der OleDbParameter-Objekte der OleDbParameterCollection hinzugefügt werden, muss daher direkt der Position des Fragezeichenplatzhalters für den Parameter entsprechen.
Hinweis Wenn die Parameter in der Auflistung nicht den Anforderungen der auszuführenden Abfrage entsprechen, kann ein Fehler auftreten.
Beispiel aus der MSDN
public void CreateMyOleDbCommand(OleDbConnection myConnection,
string mySelectQuery, OleDbParameter[] myParamArray)
{
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
myCommand.CommandText = "SELECT CustomerID, CompanyName FROM Customers WHERE Country = @Country AND City = City"; // das liefert dir ja der COmmandoBuilder auch zurück, halt nur mit Fragezeichen "?"
// keine Ahnung warum man zwei mal das gleiche zuweisen soll
myCommand.Parameters.Add(myParamArray);
for (int j=0; j<myParamArray.Length; j++)
{
myCommand.Parameters.Add(myParamArray[j]) ;
}
string myMessage = "";
for (int i = 0; i < myCommand.Parameters.Count; i++)
{
myMessage += myCommand.Parameters[i].ToString() + "\n";
}
MessageBox.Show(myMessage);
}
hier ist ein bisschen Code der von MS selber generiert wurde, also unterstelle ich ihm das er richtig ist.
MeetingTypeSqlInsert.CommandText = "INSERT INTO sacafm.Room_MeetingType(idMeetingType, MeetingTypeDesc) VALUES (@idMe" +
"etingType, @MeetingTypeDesc); SELECT idMeetingType, MeetingTypeDesc FROM sacafm." +
"Room_MeetingType WHERE (idMeetingType = @idMeetingType)";
MeetingTypeSqlInsert.Connection = this.SqlServer;
MeetingTypeSqlInsert.Parameters.Add(new System.Data.SqlClient.SqlParameter("@idMeetingType", System.Data.SqlDbType.Int, 4, "idMeetingType"));
MeetingTypeSqlInsert.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MeetingTypeDesc", System.Data.SqlDbType.NVarChar, 255, "MeetingTypeDesc"));
Dort nutzt MS folgenden Konstruktor
SqlParameter(<ParameterName>,<DatenbankTyp>,<Größe>,<Spalte die als Quelle dienen soll>);
using System.Configuration
Console.WriteLine("OS: " & Environment.OSVersion.ToString)
Console.WriteLine("Machine: " & Environment.MachineName & "." & Environment.UserDomainName)
Console.WriteLine("User: " & Environment.UserName())
Damit kann man ein parr Info dem Rechner entlocken. 😉
Wenn du noch ein Wochenende warten kannst dann konvertiere ich das Projekt nach C#.
VB oder C# ist doch egal die Idee dahinter ist genau das was du willst. Das VB-Assmbly kannst du ja als DLL nutzen das stört das .Net Framework nicht.
Eine Datei bei dem Enduser enthält die aktuelle Version als Zahlen Code.
Nun schaut der Updater (Client) im Internet nach. Dafür das Php-Skript und die MySql Datenbank, diese sagen ihm nämlich ob es eine neuere Version gibt(mit Paht zur Datei).
Der Entwickler schiebt das neue Version auf einen FTP-Server und schreibt in die Datenbank diese neue Version rein.
Orginal Code (VB)
Dim WithEvents updater As updateclient.clsClient
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
updater = New updateclient.clsClient
updater.CheckForNewVersion(ProjectName, VersionNumber,
ProjectName, Application.ExecutablePath)
End Sub
...
Private Sub updater_endall() Handles updater.endall
end
End Sub
...
End Class
Module Module1
Public Const ProjectName As String = "yourappname"
Public Const VersionNumber As Integer = 25
Public VersionDate As Date = New Date(2004, 10, 25) 'not used yet!
End Module
Meine Interpretation des Codes in C#
public class Form1
{
private updateclient.clsClient withevents updater;
// XXX
public static String ProjectName = "yourappname";
public static Integer VersionNumber = 25;
public static Date VersionDate = New Date(2004, 10, 25) 'not used yet!
private void InitializeComponent()
// diese wird ja normaler weise vom Codegenerator erstellt
{
...
// hier gebe ich dir keine Garantie das es funzt
// in VB gibt es mehrere Möglichkeiten Ereignisse abzufangen
// einmal mit "Handles" oder "AddHandler"
// in C# gibt es nur eine Möglichkeit
// <Objekt>.<Ereignis> += new <Ereignishändler>(<Funktion die darauf reagieren soll>)
// dabei ist aber zu beachten das dir Funktion die gleiche Signatur hat wie das Ereignis
Form1.Load += new EventHandler(Form1_Load);
updater.endall += new EventHandler(updater_endall);
...
}
private void Form1_Load(System.Object sender,System.EventArgs e)
{
updater = New updateclient.clsClient;
updater.CheckForNewVersion(ProjectName, VersionNumber, ProjectName, Application.ExecutablePath);
}
...
private void updater_endall()
{
// weis jetzt nicht was passieren soll wenn der Updater fertig ist
}
...
}
// Module halten in VB nur Global definerte Veriablen oder Funktionen
// in C# kann dieses durch static nach empfunden werden (siehe XXX)
//Module Module1
//Public Const ProjectName As String = "yourappname"
//Public Const VersionNumber As Integer = 25
//Public VersionDate As Date = New Date(2004, 10, 25) 'not used yet!
//End Module
Hier ist ein Beispiel aus der MSDN
using System;
using System.Threading;
public class ThreadExample
{
// Funktion die durch einen anderen Thread ausgeführt werden soll
public static void ThreadProc()
{
for (int i = 0; i < 10; i++)
{
// gebe mir mal "i" aus
Console.WriteLine("ThreadProc: {0}", i);
// genug getan schlafen, bin müde
Thread.Sleep(0);
}
}
public static void Main()
{
// Ausgabe das Programm startet
Console.WriteLine("Main thread: Start a second thread.");
// neuen Thread(Kind) anlegen und ihm sagen wo sein Anfang ist
Thread t = new Thread(new ThreadStart(ThreadProc));
// Thread(Kind) starten, also Let´s fetz
t.Start();
// Hauptthread soll aber auch eine Ausgabe machen
for (int i = 0; i < 4; i++)
{
// Hauptthread sag mal was, schreib was auf die Console
Console.WriteLine("Main thread: Do some work.");
// ja das war anstregend drum schlaf mal Hauptthread
Thread.Sleep(0);
}
// Hauptthread wil aufhören, muss aber auf sein Kind warten
// sonst kann er nicht beendet werden
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
// Hauptthread wartet bis Kind fertig ist
t.Join();
// geschaft Meldung an USER
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();
}
}
Ich denke das Beispiel sollte dir helfen, um dein Problem zulösen
So könnte deine Funktion aussehen, die du am anfang auch beschrieben.
public static int SummeGeraderZahlenBis(int n)
{
int sum = 0;
for(int i = 1; i < n; i++)
{
if((i % 2) == 0)
{
sum += i; // Summer der geraden Zahlen
}
}
return sum;
}
Teile sind ja von Noodles siehe oben
bin mir jetzt nicht sicher denke aber das die Parameter erst bei der übergabe zu DBServer eingesetzt werden. So wie bei den Ausgabe Strings wo man mit Hilfe {0} einen Paramerter varieren kann.
ich würde das mit einem eigen Thread lösen -> siehe System.Threading
so kannst du in aller ruhe püfen und die GUI läuft weiter
Frage:
Ist den das Device noch dar? Das geht ja ab und zumal verloren und somit auch seine Datem im Speicher.
Ist das DataSet ein typerisiertes DataSet?
Aber un abhängig davon benutze reine Sql-Statments
"Select * From verlag" und "Select * From buch".
public static void main(String[] args)
{
DataSet aDs = new myDataSet(); // typerisertes DataSet erstellen
//DataSet aDs = new DataSet(); Fehler -> erstellt ein normales DataSet
LoadSql("Select * From verlag","Verlag",aDs); // von der Datenbank die Tabelle Verlag holen
LoadSql("Select * From buch","Buch",aDs); // von der Datenbank die Tabelle Buch holen
FillTree_Root(aDs) // TreeView füllen
}
public void FillTree_Root( myDataSet arg)
{
TreeNode aNode; // neuen Knoten erstellen
foreach(myDataSet.VerlagRow aRow in (myDataSet.VerlagRow)arg.Verlag.Rows)
// die Verlagstabelle durch gehen und für jeden Verlag einen Eintrag machen
{
aNode = new TreeNode(aRow.Verlagname);
// die entsprechenden Buecher aus dem Verlag als Unterknoten dem Verlag zuweisen
FillTree_Child(aRow.getBuecherRows(), aNode);
// den Verlag dem Steuerelement <TreeView> zuweisen
myTreeView.add(aNode);
}
}
public void FillTree_Child(DataRow[] theRows, TreeNode theNode)
{
TreeNode aNode; // neuen Unterknoten erstellen
foreach(DataRow aRow in theRows)
// durch das Array durch gehen und für jeden Eintrag einen neuen Unterknoten anlegen
{
aNode = new TreeNode(aRow["Buechertitel"].toString()); // neuer Unterknoten
// den neuen Unterknoten dem Verlag zuweisen
theNode.add(aNode);
}
}
public void LoadSql(String sql, String table, DataSet Ds)
{
try
// ein try-catch um Fehler bei holen der Daten abzufangen
{
// neues Verbindungsobjekt erstellen
System.Data.Odbc.OdbcConnection Connection = new System.Data.Odbc.OdbcConnection ("DSN=Microsoft Access-Datenbank;DefaultDir=C:\\;DriverId=25;DBQ=C:\\Datenbank.mdb;Ma" +
"xBufferSize=2048;FIL=MS Access;PageTimeout=5;UID=admin");
// Verbindung öffnen
Connection.Open();
// neuen Adapter erstellen mit dem Sql für die benötigen Daten und dem Verbindungsobjekt
System.Data.Odbc.OdbcDataAdapter Adapter = new System.Data.Odbc.OdbcDataAdapter(sql,Connection);
// Daten aus der Datenbank in das DataSet ziehen, und Tabellennamen dafür vergeben
Adapter.Fill(Ds,table);
}
catch(OdbcException ex)
{
// falls Fehler bitte Meldung an USER
Messagebox.Show(ex.Message);
}
finally
{
// auf jeden Fall zu Schluss die Verbindung wieder schließen, auch bei einem Fehler
Connection.Close();
}
}
der Code sollte eigentlich funz, versuche ihn mal zu Debugen Schritt für Schritt und überlege was er beim nächsten Schritt machen soll und ich denke dann kommt das Verständnis von ganz allein.
Wenn du Fragen hast, dann Frage
Hi,
ein Reader kann nur einmal die Daten durchlaufen, und wenn die Verbindung zu ist dann wird der Inhalt auch gelöscht (denke ich zumindestens).
Mein Vorschlag wäre:
(davon gehe ich mal aus, das du hast zwei Tabellen die durch eine Relation verbunden sind. In der einen Tabelle sind alle Verlage drin und in der zweiten sind alle Bücher drin und ein Schlüssel der auf den Verlag verweist.)
Bei dieser Situation würde ich dir ein DataSet mit Relationen empfehlen. So brauchst du nur die Verlagtabelle durch gehen. Da jede Zeile der Verlagtabelle weiss welche Bücherzeile zu ihr gehört.
public void FillTree_Root( myDataSet arg)
{
TreeNode aNode;
foreach(myDataSet.VerlagRow aRow in (myDataSet.VerlagRow)arg.Verlag.Rows)
{
aNode = new TreeNode(aRow.Verlagname);
FillTree_Child(aRow.getBuecherRows(), aNode);
myTreeView.add(aNode);
}
}
public void FillTree_Child(DataRow[] theRows, TreeNode theNode)
{
TreeNode aNode;
foreach(DataRow aRow in theRows)
{
aNode = new TreeNode(aRow["Buechertitel"].toString());
theNode.add(aNode);
}
}
So jetzt zur Frage wie erstelle man so ein DataSet. siehe hier Exemplarische Vorgehensweise: Erstellen von Datasets mit Tabellen, Schlüsseln und 1:n-Beziehungen
Was ich in dem Beispeil verwendet habe ist ein typersiertes DataSet, wie man dieses erstellt siehe hier Erstellen neuer typisierter Datasets mit dem XML-Designer
Und nun zur Datenbank Anbindung
Das ist abhängig von der verwendeten Datenbank, im Prinzip sind sie aber alle gleich. Du musst nur die entsprechenden Klassen ansprechen. (hier ist es für den SQL-Server)
SqlConnection SqlConn = new SqlConnection(ConnectionString);
SqlConn.Open();
SqlDataAdapter SqlAdapter = new SqlDataAdapter(SelectString, SqlConn);
SqlAdapter.Fill(<DataSet oder Tabelle die gefüllt werden soll>,TabellennameString);
SqlConn.Close();
ich hoffe das ich dir helfen konnte 🙂
Die Datei muss die Werte durch einen Tab getrennt sein (Endung ist egal). Dann brauchst du nur noch eine Funktion die die Werte den Lable zuweisen., diese muss ein Stringarray als Parameter haben.
Hier ein Stück Code
...
FileInfo aFileInfo = new FileInfo(aPaht);
StreamReader srReadLine = new StreamReader((System.IO.Stream)aFileInfo.OpenRead(),System.Text.Encoding.Default);
srReadLine.BaseStream.Seek(0, SeekOrigin.Begin);
SetLableText(srReadLine.ReadLine().Split((char)9));
srReadLine.Close();
....
Ich hoffe das ich dir helfen konnte. 🙂
Konstuktor in C# sieht von den Parametern so aus zumindestens einer
public Device(int adapter, DeviceType deviceType, Control renderWindow, CreateFlags behaviorFlags, PersentParameters presentationParameters)
So jetzt Erklärung:
adapter gibt die Grafikkarte an in dem meisten Fällen 0
deviceType fordert einen Wert der Enumeration DeviceType (siehe unten was die einzelen Werte bedeuten)
renderWindoe normaler weise das Fenster wo später die Grafik dargestellt werden soll
behaviorFlags fordert einen Wert der Enumeration CreateFlags (siehe unten was die einzelen Werte bedeuten)
presentationParameters gibt einzele Paramerte an wie SwapEffect, Windowed (mehr dazu später)
Enumeration "DeviceType"
Hardware Die Rasterisation werden in der Grafikkarte durchgeführt. Vecrtices können entweder durch CPU oder GPU trasformiert,beleuchtet und so weiter.
Dabei wird die HAL gefragt was für Funktionen die GPU kann die anderen werden durch Software (CPU) gelöst.
Reference sollte man nicht nutzen, ist zum testen geeignet ist nur in der SDK-DirectX enthalten
Software hier hat man die Möglichkeit Softwarelösungen anderer Hersteller zunutzen
Enummeration "CreateFlags"
MixedVertexProcessing hier werden Hardware und Software Transformationen und Belichtung unterstützt (optimal)
HardwareVertexProcessing nur Hardware T&L
SoftwareVertexProcessing nur Software T&L (das belastet die CPU)
PureDevice hier werden nur Operationen unterstützt die die Grafikkarte kann
(ist die schnellste)
Klasse "PersentParameters"
Hier gibt es auch eine Enumeration die das Verhalten festlegt bezüglich des BackBuffers. -> SwapEffect
Discard effizienste Darstelleung, ist aber unklar ob der BackBuffer nach der Aussgabe noch vrhanden ist
Copy kopiert den BackBuffer in den FrontBuffer(Bildschirm), wird aber nich synchronisiert dadurch können unschöne Effekte auftretten
Flip da werden mehrere BackBuffer unterstützt und immer hin und her gewechselt, eine Synchronisierung verhindert unschöne Effekte
Ein Aufruf könnte dann so aussehen
PresentParameters PresentParams = New PresentParameters();
Device objDevice;
PresentParams.Windowed = true;
PresentParams.SwapEffect = SwapEffect.Discard;
objDevice = new Device(0, DeviceType.Hardware, this, CreateFlags.MixedVertexProcessing, PresentParams);
Ich gehe mal davon aus das du eine DataTable oder DataSet als Datengrundlage hast.
Und dort könntest du dann das Ergeignis der DataRow abfangen. Das Ereignis heißt "RowChanged" -> das gibt dir auch gleich die Row mit die geändert wurde.
Wenn ich den Thread richtig verfolgt habe dann, sollen zwei Forms miteinander kommunizieren und dies über eine dritte Klasse.
Da sollte dein oben stehender Code eigentlich laufen, bis auf das noch die Singelton fehlt. Das ist notwendig, damit beide Forms auf die gleiche Instanz der Klasse zurück greifen. Sonst erstellen diese immer wieder eine neue Instanz.
Damit man eine Klasse Singelton fähig ist braucht man nicht viel.
public class ExampelSingelton
{
private static ExampelSingelton my_instanz;
private ExampelSingelton()
{
.....
}
public static getExampelSingelton()
{
if(my_instanz == null)
{
my_instanz = new ExampelSingelton();
}
return my_instanz;
}
So jetzt können deine beiden Forms auf ein und die selbe Instanz zugreifen und somit Werte übergeben.
Im allgemeinen würde ich dieses Problem mit Eventhandling / Interface lösen.
So das der Code der beiden Forms nur in einer Klasse hinter den Forms liegt, so kann man innerhalb von kurzer Zeit eine Desktop-Anwendung auf eine Web-Anwendung umstellen oder GTK+.
Hi,
Warum nutzt du ein Panel ???
Ich hätte das ohne Panel gelöst, der TreeView kennt doch auch die Eigenschaft "Visible".
Aber was bei dir sein kann das der TreeView eigentlich größer ist als dargestellt und da durch ein Scrollbalken auftaucht. Gebe den TreeView genau die Größe von dem Panel oder ein stück kleiner. Und ich denke dann sollte dein Problem gelöst sein.
Lösung: Mathe Formelwerk
Einheitskreis = Sinussatz ,Cosinussatz
im Framework ist das aber mit Vorsicht zugenissen da Math.Sin ein Bogenmaß als Prameter erwartet. (Bogenmaß = Winkel * PI/180)
Das kommt daher das bei ShowDialog() solange wartet bis die UI wieder geschlossen wird.
Eine Möglichkeit wäre das du den Aufruf "ShowDialog" in "Show" änderst, oder die "Additem"-Aufruf vor den "ShowDialog"-Aufruf legst oder du einen neuen KOnstruktor anlegst der dein Item als Parameter erwartet.
Ok dann nehmen wir halt den Cast raus um zu schauen ob er überhaupt eine Instanz erstellt. Ich habe bei mir auch einen kleinen Fehler entdeckt, CreateInstanze verlangt nach einem String, aber dieser String muss einen Typ aus dem Assembly entsprechen.
sorry, aber latebinding ist nicht unbedingt meine Stärke
so schreibe dieses doch mal bitte in den Try-Block
asm = Assembly.LoadFrom(files[i].FullName);
string typeName = t.FullName;
object lateBoundObj = asm.CreateInstance(typeName);
Wenn das ohne Fehler laufen sollte dann, lass den Typ des Objektes ausgeben("lateBoundObj.GetType()").
Hallo zusammen,
ich habe ein Programm geschrieben was einen Import macht und Informationen an in die Console abgibt. Nun möchte ich das die Console erfährt bei welchen Datensatz sich das Programm befindet.
Dieses soll aber nicht fortlaufend sein, sondern immer in der gleichen Zeile passieren.
Nun wie kann ich den Cursor setzen, so das er immer in der gleichen Zeile bleibt?
Probiere doch mal diesen Try-Block
try
{
asm = Assembly.LoadFrom(files[i].FullName);
plugins[i] = (IPlugIn)asm.CreateInstance("Klassenname");
Console.WriteLine("OK");
}
ich würde so vorgehen
Code:
public Array KillDuplicat(String[] args)
{
ArrayList temp = new ArrayList();
temp.Add(args[0]);
long readpos = 0;
for (long i = 1; i<=args.Length - 1; i++)
{
if(args[i] != args[readpos])
{
temp.Add(args[i]);
readpos = i;
}
}
return temp.ToArray();
}