-1

理解を深めるために編集...

Form1.cs ファイルと別の Class.cs ファイルがあります。

Form1私は Class.myFunc() を呼び出す bgWorker を持っています。これは 3 つのループを実行しforeach、各ループstring ClientNameは やなどの値を返しますstring ClientOrder

これらの値を Class.myFunc から bgWorker (これは の中Form1にあることを思い出してください) に戻し、それらを ListView、Textbox などに挿入したいと考えています。

問題は、Class.myFunc から BgWorker に文字列値を返す方法です。

誰かがこれで私を助けてくれることを願っています...

Form1.cs

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    ControlsHelper.ControlInvike(listProcess, () => listProcess.Items.Add("Current").Name = "item1");
            myOtherClass cp = new myOtherClass();
            cp.myFunc();
}

Class.cs

public void myFunc()
{
    foreach (string Client in Clients)
    {
           // Do something
           // Return Client and insert into listview, richtextbox, W/E
    }
} 
4

3 に答える 3

1

Daniel Hilgarth の回答を拡張するには、BGW がコンテキスト内に存在しない場合、Class.cs進行状況を更新できるようにパラメーターとして渡すことはできません。DoWork 署名でobject senderは、送信先の BackgroundWorker としてキャストする BGW ですmyFunc

だからあなたは持っているでしょう

public void myFunc(BackgroundWorker bgw)
{
    foreach (string Client in Clients)
    {
       // Do something
       // Return Client and insert into listview, richtextbox, W/E

       var returningObjects = List<string>();  //I assume this will be a list of strings based on your question.
       returningObjects.Add(ClientName);
       returningObjects.Add(ClientOrder);
       returningObjects.Add(Client3rdThing);

       bgw.ReportProgress(0,returningObjects)
    }
} 

ジェネリックList<string>を使用するよりもさらに優れているのは、必要なすべてのアイテムを持つ独自のクラスを作成し、リスト インデックスを参照する代わりにそれらを明示的に呼び出すことができることです。

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bgw = sender as BackgroundWorker;
    ControlsHelper.ControlInvike(listProcess, () => listProcess.Items.Add("Current").Name = "item1");
            myOtherClass cp = new myOtherClass();
            cp.myFunc(bgw);
}

次に、 ProgressChanged イベントハンドラーで

private void bgWorker_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
   //Set the  e.UserState to whatever you need. It is of type Object.
    var returnedObjects = e.Userstate as List<string>;
    if(returnedObjects != null)
    {
        //do stuff with each of your returnedObjects[i];
    }

}

スレッド セーフを確保するために、この拡張メソッドをコントロールに使用します。このロジックが拡張メソッドにまとめられているのは本当に素晴らしいことです。Invoke 構造を呼び出す必要があるときはいつでも Invoke 構造について考える必要はありません。呼び出すだけです。

また、BackgroundWorker を使用してインスタンス化するときは、必ずすべてを結び付けてください。

bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
于 2012-09-18T15:23:18.153 に答える
1

これを(ab)使用BackgroundWorker.ReportProgressして、値を2番目のパラメーターとして渡すことができます。

于 2012-09-18T14:55:41.570 に答える
0

まず、本当にマルチスレッドが必要かどうかを確認してください。リストのロードが完了するまで、GUI の更新を防止するだけで十分な場合があります。

マルチスレッドが必要な場合は、3 つのループをその順序で実行する必要があることを確認してください。そうでない場合は、1 つではなく 3 つの bgWorkers が必要です。

最後に、スレッドセーフに関する優れた記事がたくさんあります。リストビューを直接更新できないことがわかります。スレッドセーフなデリゲートを使用する必要があります。

于 2012-09-18T15:05:34.447 に答える