Laden...

Threads mit mehreren Parametern

Erstellt von cesharper vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.818 Views
C
cesharper Themenstarter:in
5 Beiträge seit 2008
vor 15 Jahren
Threads mit mehreren Parametern

Hallo liebe C# Gemeinde,
ich bin noch Neuling in C# und habe gerade mein erstes kleines Programm geschrieben.
Das Programm soll Ordner, Unterordner und die darin enthaltenen Dateien kopieren. Das Programm arbeitet bisher einwandfrei nur hat es Probleme mit dem kopieren von größeren Dateien. Wie schon in anderen Forenbeiträgen schon oft erwähnt wurde hängt natürlich das GUI, sodass ich diese Methode gerne in einen Thread auslagern möchte.
Das Problem ist das der Methode 3 Argumente übergeben werden müssen.
Gibt es denn eine Möglichkeit wie ParameterizedThreadStart die mehr als ein Parameter übergeben kann? Und wie genau funktioniert das mit dem Parameter übergeben das als "object" angegeben muss?


        private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
        {


            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            // If the source directory does not exist, throw an exception.
            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory does not exist, create it.
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }


            // Get the file contents of the directory to copy.
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo file in files)
            {

                // Create the path to the new copy of the file.
                string temppath = Path.Combine(destDirName, file.Name);

                // Copy the file.
                file.CopyTo(temppath, true);

            }

            // If copySubDirs is true, copy the subdirectories.
            if (copySubDirs)
            {

                foreach (DirectoryInfo subdir in dirs)
                {

                    // Create the subdirectory.
                    string temppath = Path.Combine(destDirName, subdir.Name);

                    // Copy the subdirectories.
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs);

                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {

<-----hier steht noch anderer Code------------>

            if (checkBox2.Checked)
            {
                string targetpath, sourcepath, folder1, folder1a;
                sourcepath = prepath + tnum + desktop;
                targetpath = target1 + tnum + desktop;
                if (Directory.Exists(sourcepath))
                {
                    //ParameterizedThreadStart pts = new ParameterizedThreadStart(this.DirectoryCopy);
                    //Thread thread = new Thread(pts);
                    //thread.Start(sourcepath, targetpath, true);
                    DirectoryCopy(sourcepath, targetpath, true);
                    folder1 = FileCounter(sourcepath).ToString();
                    folder1a = FileCounter(targetpath).ToString();
                    if (folder1 == folder1a)
                        richTextBox1.Text = richTextBox1.Text+"Kopiervorgang von Desktop erfolgreich!" + Environment.NewLine + "Quelle hat " + folder1 + " Dateien" + Environment.NewLine + "Ziel hat " + folder1a + " Dateien" + Environment.NewLine;
                    else
                        richTextBox1.Text = richTextBox1.Text+"Kopieren von Desktop fehlgeschlagen" + Environment.NewLine;
                }
                else
                    richTextBox1.Text = richTextBox1.Text + @"Der Quellordner Desktop ist nicht vorhanden!" + Environment.NewLine;
                

            }


Danke schon mal im Vorraus......

3.430 Beiträge seit 2007
vor 15 Jahren

Hi,

da es sich bei dem Parameter vom ParameterizedThreadStart um ein object handelt. Kannst du deine drei Variablen einfach in einen Object-Array packen.
Diesen kannst du dann dem Thread übergeben und anschliessend kannst du den Array wieder auflösen.

so ungefähr


string v1;
string v2;
string v3;
object[] arr = new object[3];
arr[1]=v1;
arr[2]=v2;
arr[3]=v3;

....
Thread.Start(arr);
...

private void myThreadMethod(object data)
{
     object[] arr = (object[])data;
     string v1 = arr[0].ToString();
     ......
}


Da könnten sich zwar ein paar Syntaxfehler eingeschlichen, aber die wird dein Compiler schon finden =)

Vielleicht gibt es auch noch eine elegantere Methode das zu machen.....

mfg
michlG

C
cesharper Themenstarter:in
5 Beiträge seit 2008
vor 15 Jahren

wow danke für die schnelle Antwort MichlG.
Ich denke ich hab verstanden wie das mit dem Object funktioniert und danke dir für deine "kleine Aufklärung".

Leider bekomme ich immer noch eine Fehlermeldung:
Fehler 1 Keine Überladung für "DirectoryCopy" stimmt mit dem Delegaten "System.Threading.ParameterizedThreadStart" überein. C:\Documents and Settings\bj1480\My Documents\Visual Studio 2008\Projects\copyfolders\WindowsApplication1\Form1.cs 180 52 WindowsApplication1

mein geänderter Code war:


                 string overwrite = "true";
                    object[] arr = new object[3];
                    arr[1] = sourcepath;
                    arr[2] = targetpath;
                    arr[3] = overwrite;

                    ParameterizedThreadStart pts = new ParameterizedThreadStart(this.DirectoryCopy);
                    Thread thread = new Thread(pts);
                    thread.Start(arr);

Die beiden Strings sourcepath und targetpath sind deklariert und mit einem Wert beladen.
Die Deklaration der Methode lautete der Methode:
private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)

Da ich mit Überladungen Datentypen verstehe die nicht in den Übergabeparametern stehen versuchte ich auch folgendes:


                    bool overwrite = true;
                    object[] arr = new object[3];
                    arr[1] = sourcepath;
                    arr[2] = targetpath;
                    arr[3] = overwrite;

...was allerdings den gleichen Fehler hervorruft.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo cesharper,

DirectoryCopy darf eben nur einen Parameter vom Typ Objekt bekommen.

herbivore

C
cesharper Themenstarter:in
5 Beiträge seit 2008
vor 15 Jahren

DirectoryCopy benötigt leider 3 Parameter

private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)

3.430 Beiträge seit 2007
vor 15 Jahren

DirectoryCopy benötigt leider 3 Parameter

private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)

nö, nur einen. Da du dieses drei Variablen ja in den object[] gepackt hast deshalb muss das so aussehen:


private void DirectoryCopy(object data)

mfg
michlG

C
cesharper Themenstarter:in
5 Beiträge seit 2008
vor 15 Jahren

Fehler 1 Der Name "sourceDirName" ist im aktuellen Kontext nicht vorhanden.
.
.
Fehler 3 Der Name "destDirName" ist im aktuellen Kontext nicht vorhanden.
.
.
Fehler 8 Der Name "copySubDirs" ist im aktuellen Kontext nicht vorhanden.

.... nun werden alle übergebenen Parameter nicht gefunden.
Hab ich da etwas überlesen?


using System;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void DirectoryCopy(object data)
        {


            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            // If the source directory does not exist, throw an exception.
            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory does not exist, create it.
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }


            // Get the file contents of the directory to copy.
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo file in files)
            {

                // Create the path to the new copy of the file.
                string temppath = Path.Combine(destDirName, file.Name);

                // Copy the file.
                file.CopyTo(temppath, true);

            }

            // If copySubDirs is true, copy the subdirectories.
            if (copySubDirs)
            {

                foreach (DirectoryInfo subdir in dirs)
                {

                    // Create the subdirectory.
                    string temppath = Path.Combine(destDirName, subdir.Name);

                    // Copy the subdirectories.
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs);

                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
                string v1 =@"c:\test";
                string v2 =@"c:\test1";
                bool v3=true;
                object[] arr = new object[3];
                arr[1]=v1;
                arr[2]=v2;
                arr[3]=v3;
                ParameterizedThreadStart pts = new ParameterizedThreadStart(this.DirectoryCopy);
                Thread thread = new Thread(pts);
                thread.Start(arr);

        }
    }
}

3.430 Beiträge seit 2007
vor 15 Jahren

Hi,

ja das ist klar, dass du da diese Exceptions erhälst, da du die Variablen ja nicht deklariert hast.


private void DirectoryCopy(object data)
{
     //Data aufsplitten
     object[] arr = (object[])data;
     String sourceDirName = arr[0].ToString();
     String destDirName = arr[1].ToString();
     .......

//... Der Rest der Methode

mfg
michlG

871 Beiträge seit 2005
vor 15 Jahren

Hallo,

du verwendest in deiner Methode variablen welche nicht existieren. Mach folgendes:


private void DirectoryCopy(object data)
{
    string sourceDirName = ( string ) (( object[] ) data )[0];
    string destDirName = ( string ) (( object[] ) data )[1];
    bool copySubDirs = ( bool ) (( object[] ) data )[2];

    .
    .
    .
}

etwaige Syntaxfehler sind in diesem ungetesteten code selbst zu beheben 🙂

Grüsse,
Egon

C
cesharper Themenstarter:in
5 Beiträge seit 2008
vor 15 Jahren

😄danke das hatte ich überlesen...obwohl das ja eigentlich logisch ist

49.485 Beiträge seit 2005
vor 15 Jahren
3.971 Beiträge seit 2006
vor 15 Jahren

Um das Problem mit dem Down- und Upcasten zu umgehen(fehleranfällig), kann man auch eine spezielle Parameterklasse schreiben. Im Konstruktor werden die Argumente übergeben und als Member gespeichert. Anschließend einen neuen Thread mit einer Funktion aus der Klasse (nicht static) erstellen. In dem Thread kann man mit this auf die entsprechenden Parameter zugreifen. Zu beachten ist, immer eine Instanz als Variable zu speichern, sonst räumt der GC den noch arbeitenden Thread auf.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

C
252 Beiträge seit 2007
vor 15 Jahren

Man kann durchaus mehrere parameter mitgeben. siehe Threading in C#

3.430 Beiträge seit 2007
vor 15 Jahren

Hi,

Man kann durchaus mehrere parameter mitgeben. siehe Threading in C#

ich habe die von dir gepostete Seite jetzt dreimal überflogen und dabei habe ich nirgends ein Beispiel gesehen, wo mehrere Parameter übergeben werden.

Kannst du bitte diese Stelle der Seite posten, denn dass das auch mit mehreren Parametern gehen soll ist mir, wie wahrscheinlich auch vielen anderen nicht bekannt.

mfg
michlG

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo michlG,

static void Main() {
  Thread t = new Thread (delegate() { WriteText ("Hello"); });
  t.Start();
}
static void WriteText (string text) { Console.WriteLine (text); }

Die WriteText-Methode könnte beliebige Parameter haben, also auch mehrere. Die Parameter sind praktischerweise zudem typsicher.

herbivore

3.971 Beiträge seit 2006
vor 15 Jahren

ich habe die von dir gepostete Seite jetzt dreimal überflogen und dabei habe ich nirgends ein Beispiel gesehen, wo mehrere Parameter übergeben werden.

ergänzend: hier wurden die seit .NET 2.0 neu eingeführten anonymen Delegaten verwendet, dort generiert (zaubert) der Compiler eine entsprechende neue Funktion und ruft diese anschließend auf. Das Tolle daran, alle Member und Variablen sind auch in der neuen Funktion verfügbar

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...