C# 在.NET中返回数据的线程

C# 在.NET中返回数据的线程,c#,multithreading,C#,Multithreading,我在写一个程序,通常从五个线程开始。螺纹以不确定的顺序返回。每个线程都在调用一个返回列表的方法 我正在这样做: var masterList = List<string>(); foreach (var threadParam in threadParams) { var expression = threadParam ; ThreadStart sub = () => MyMethod(expressions); var thread = n

我在写一个程序,通常从五个线程开始。螺纹以不确定的顺序返回。每个线程都在调用一个返回列表的方法

我正在这样做:

var masterList = List<string>();    
foreach (var threadParam in threadParams)
{
    var expression = threadParam ;
    ThreadStart sub = () => MyMethod(expressions);
    var thread = new Thread(sub)
    {
        Name = expression
    };

    listThreads.Add(thread);
    thread.Start();
}

var abort = true;
while (abort) //Wait until all threads finish
{
    var count = 0;
    foreach (var list in listThreads)
    {
        if (!list.IsAlive)
        {
            count++;
        }
    }

    if (count == listThreads.Count)
    {
        abort = false;
    }
}

查看WaitHandle类和WaitHandle.WaitAll(我在一些代码中使用了ManualResetEvent类作为WaitHandle,但这只是一个示例。我不知道是否有更好的方法适合您的情况)。启动所有五个线程,给它们一个主列表的引用,在添加到主列表时锁定此列表,然后发出完成信号。使用WaitHandle.WaitAll阻塞,直到所有五个线程都发出完成信号。

最好的方法是使每个线程都成为自己的对象。不要与其他对象混在一起,只需构造它(传递变量),将自己添加为侦听器并启动它

完成后,它将值存储在成员变量中,并通知您的侦听器

您的侦听器可以在空闲时检索这些值

显而易见的快捷方式是直接将值返回给侦听器,但您以后可能会发现这个版本更灵活(实际上没有更多的代码)

使用


下面是一个例子:

using System;
using System.Threading;

class ThreadSleeper
{
    int seconds;
    AutoResetEvent napDone = new AutoResetEvent(false);

    private ThreadSleeper(int seconds)
    {
        this.seconds = seconds; 
    }

    public void Nap()
    {
        Console.WriteLine("Napping {0} seconds", seconds);
        Thread.Sleep(seconds * 1000);
        Console.WriteLine("{0} second nap finished", seconds);
        napDone.Set();
    }

    public static WaitHandle DoSleep(int seconds)
    {
        ThreadSleeper ts = new ThreadSleeper(seconds);
        Thread thread = new Thread(new ThreadStart(ts.Nap));
        thread.Start();
        return(ts.napDone);
    }
}

public class OperationsThreadsWaitingwithWaitHandle
{
    public static void Main()
    {
        WaitHandle[] waits = new WaitHandle[2];
        waits[0] = ThreadSleeper.DoSleep(8);
        waits[1] = ThreadSleeper.DoSleep(4);

        Console.WriteLine("Waiting for threads to finish");
        WaitHandle.WaitAll(waits);
        Console.WriteLine("Threads finished");
    }
}

查看链接


当然,您也可以使用常规代理和

请注意,您描述的模式通常被描述为一种背景工作,承诺以后会有回报(如果可以的话,投资回报)

下面是一个简短的示例,以控制台程序的形式

输出:

sequential: 3224 ms
parallel: 2074 ms
当然,因为我没有构造显式线程,所以我把它留给线程池系统来计算并行运行的线程数

还提供了通过回调方法通知后台线程何时完成的规定,以及WaitHandle支持显式检查和等待超时等

资料来源:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

namespace SO1215227
{
    public class Program
    {
        public static void Main()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var list1 = Sequence(1, 100);
            var list2 = Sequence(101, 200);
            var list3 = Sequence(201, 300);
            sw.Stop();
            Console.Out.WriteLine("sequential: " + sw.ElapsedMilliseconds + " ms");
            sw.Reset();

            Func<Int32, Int32, List<Int32>> listProducer = Sequence;
            sw.Start();
            var list1Background = listProducer.BeginInvoke(1, 100, null, null);
            var list2Background = listProducer.BeginInvoke(101, 200, null, null);
            var list3Background = listProducer.BeginInvoke(201, 300, null, null);

            list1 = listProducer.EndInvoke(list1Background);
            list2 = listProducer.EndInvoke(list2Background);
            list3 = listProducer.EndInvoke(list3Background);
            sw.Stop();
            Console.Out.WriteLine("parallel: " + sw.ElapsedMilliseconds + " ms");

            Console.Out.Write("Press enter to exit...");
            Console.In.ReadLine();
        }

        private static List<Int32> Sequence(Int32 from, Int32 to)
        {
            List<Int32> result = new List<Int32>();
            for (Int32 index = from; index <= to; index++)
            {
                result.Add(index);
                Thread.Sleep(10); // simulate I/O wait
            }
            return result;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统线程;
使用系统诊断;
名称空间SO1215227
{
公共课程
{
公共静态void Main()
{
秒表sw=新秒表();
sw.Start();
var list1=序列(1100);
var list2=序列(101200);
var list3=序列(201300);
sw.Stop();
控制台输出写入线(“顺序:+sw.ElapsedMilliseconds+“ms”);
sw.Reset();
Func listProducer=序列;
sw.Start();
var list1Background=listProducer.BeginInvoke(1100,null,null);
var list2Background=listProducer.BeginInvoke(101200,null,null);
var list3Background=listProducer.BeginInvoke(201300,null,null);
list1=listProducer.EndInvoke(list1Background);
list2=listProducer.EndInvoke(list2Background);
list3=listProducer.EndInvoke(list3Background);
sw.Stop();
Console.Out.WriteLine(“并行:+sw.elapsedmillyses+“ms”);
Console.Out.Write(“按enter键退出…”);
Console.In.ReadLine();
}
专用静态列表序列(Int32-from、Int32-to)
{
列表结果=新列表();

对于(Int32 index=from;索引与我的想法相同…但有一个更好的答案:(
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;

namespace SO1215227
{
    public class Program
    {
        public static void Main()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var list1 = Sequence(1, 100);
            var list2 = Sequence(101, 200);
            var list3 = Sequence(201, 300);
            sw.Stop();
            Console.Out.WriteLine("sequential: " + sw.ElapsedMilliseconds + " ms");
            sw.Reset();

            Func<Int32, Int32, List<Int32>> listProducer = Sequence;
            sw.Start();
            var list1Background = listProducer.BeginInvoke(1, 100, null, null);
            var list2Background = listProducer.BeginInvoke(101, 200, null, null);
            var list3Background = listProducer.BeginInvoke(201, 300, null, null);

            list1 = listProducer.EndInvoke(list1Background);
            list2 = listProducer.EndInvoke(list2Background);
            list3 = listProducer.EndInvoke(list3Background);
            sw.Stop();
            Console.Out.WriteLine("parallel: " + sw.ElapsedMilliseconds + " ms");

            Console.Out.Write("Press enter to exit...");
            Console.In.ReadLine();
        }

        private static List<Int32> Sequence(Int32 from, Int32 to)
        {
            List<Int32> result = new List<Int32>();
            for (Int32 index = from; index <= to; index++)
            {
                result.Add(index);
                Thread.Sleep(10); // simulate I/O wait
            }
            return result;
        }
    }
}