1

メインスレッドがあり、別の n スレッドを作成します。n スレッドのそれぞれがList<String>. すべてのスレッドが終了すると、それらは結合されます。これらすべての n スレッド リストをメインスレッドのList<List<String>>BUT に入れたいと思います。メインスレッドはその上で操作できるはずですList<List<String>>。n スレッドのそれぞれがList<String>.

私は c# .NET 3.5 を持っています。static List<List<String>>

            Thread t = new Thread(someObjectForThreading.goPopulateList);
            list_threads.Add(t);
            list_threads.last().start()

list_threads 内のすべてのスレッドが続き、それらのリストにデータが入力され、それらが終了したら、次のようなものが必要です

 //this = mainThread
 this.doSomethingWith(List<List<String>>)

編集:うーん、そのようなタスクを解決する「標準的な概念」はありませんか?リスト上で動作する多くのスレッドがすべて参加すると、メインスレッドはリスト上での動作を続行できます。

Edit2:List<List<String>> listOfLists静的であってはなりません。それはすることができますpublic or private。最初に、listOfLists を操作 (およびロック) するために n スレッドが必要であり、それらのリストを挿入します。すべての n スレッドがリストの挿入を完了したら、スレッドに参加し、メインスレッドはビジネスロジックに進み、listOfLists

http://www.albahari.com/threading/レポートの一部を読み直そうと思います

4

4 に答える 4

5

次に示すのは、待機ハンドル (この場合は ManualResetEvent) を使用して、各ワーカー スレッドがメイン スレッドに作業が完了したことを通知できるようにする単純な実装です。これがある程度自明であることを願っています:

private List<List<string>> _listOfLists;

public void CreateListOfLists()
{
    var waitHandles = new List<WaitHandle>();

    foreach (int count in Enumerable.Range(1, 5))
    {
        var t = new Thread(CreateListOfStringWorker);
        var handle = new ManualResetEvent(false);
        t.Start(handle);
        waitHandles.Add(handle);
    }

    // wait for all threads to complete by calling Set()
    WaitHandle.WaitAll(waitHandles.ToArray());

    // do something with _listOfLists
    // ...
}

public void CreateListOfStringWorker(object state)
{
    var list = new List<string>();
    lock (_listOfLists)
    {
        _listOfLists.Add(list);
    }

    list.Add("foo");
    list.Add("bar");

    ((ManualResetEvent) state).Set(); // i'm done
}

各スレッドのリストをリストのメイン リストに追加している間だけロックしていることに注意してください。各スレッドには独自のリストがあるため、追加ごとにメイン リストをロックする必要はありません。わかる?

編集:

待機ハンドルを使用するポイントは、リストのリストで作業する前に、各スレッドが完了するのを待つことです。待機しないと、ワーカーがまだ文字列を追加している間に List インスタンスの 1 つを列挙しようとするリスクがあります。これにより、InvalidOperationException がスローされ、スレッドが停止します。コレクションを列挙し、同時に変更することはできません。

于 2012-08-30T21:31:11.523 に答える
1

lock各スレッドに、ステートメントで保護されたメイン スレッドのリストを更新するコールバック メソッドを提供します。

編集:

class Program
{
    static List<string> listOfStuff = new List<string>();

    static void Main(string[] args)
    {
        List<Thread> threads = new List<Thread>();
        for (int i = 0; i < 20; i++)
        {
            var thread = new Thread(() => { new Worker(new AppendToListDelegate(AppendToList)).DoWork(); });
            thread.IsBackground = true;
            threads.Add(thread);
        }
        threads.ForEach(n => n.Start());
        threads.ForEach(n => n.Join());
        Console.WriteLine("Count: " + listOfStuff.Count());
        Console.ReadLine();
    }

    static void AppendToList(string arg)
    {
        lock (listOfStuff)
        {
            listOfStuff.Add(arg);
        }
    }
}

public delegate void AppendToListDelegate(string arg);
class Worker
{
    AppendToListDelegate Appender;

    public Worker(AppendToListDelegate appenderArg)
    {
        Appender = appenderArg;
    }

    public void DoWork()
    {
        for (int j = 0; j < 10000; j++)
        {
            Appender(Thread.CurrentThread.ManagedThreadId.ToString() + "." + j.ToString());
        }
    }
}
于 2012-08-30T21:12:58.033 に答える
1

static List<List<String>>ローカルList<List<String>>にしてオブジェクトに渡すのではなく、スレッドが実行されます。もちろん、List複数のスレッドからアクセスされるため、同期ラッパーでラップする必要があります。

List<List<String>> list = ArrayList.synchronized(new ArrayList<List<String>>());

// later
SomeObject o = new SomeObjectForThreading(list);
Thread t = new Thread(o.goPopulateList);
list_threads.Add(t);
list_threads.last().start();

// even later
this.doSomethingWith(list);

ではo.goPopulateList

List<String> temp = new ArrayList<String>();
temp.add(random text);
temp.add(other random text);
this.list.add(temp); // this.list was passed in at construct time
于 2012-08-30T21:09:43.360 に答える
0
private void someObjectForThreading.goPopulateList()
{
    Do threaded stuff...
    populate threaded list..

    All done..
    for (List list in myThreadedList)
    {
        myMainList.Add(list);
    }
}
于 2012-08-30T21:28:25.600 に答える