Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#等待多个线程完成_C#_Multithreading - Fatal编程技术网

C#等待多个线程完成

C#等待多个线程完成,c#,multithreading,C#,Multithreading,我有一个windows窗体应用程序,我正在检查所有串行端口,以查看是否连接了特定设备 这是我如何剥离每一条线。下面的代码已经脱离了gui主线程 foreach (cpsComms.cpsSerial ser in availPorts) { Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev)); t.Start((object)ser);//start thread and pass it the

我有一个windows窗体应用程序,我正在检查所有串行端口,以查看是否连接了特定设备

这是我如何剥离每一条线。下面的代码已经脱离了gui主线程

foreach (cpsComms.cpsSerial ser in availPorts)
{
    Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
    t.Start((object)ser);//start thread and pass it the port
}
我希望下一行代码等待所有线程完成。
我曾尝试在其中使用
t.join
,但这只是线性地处理它们

生成线程结果后,将其存储在列表中,并迭代该列表-然后在迭代期间调用join。您仍然可以线性连接,但它应该执行您想要的操作。

使用AutoResetEvent和ManualResetEvent类:

List<Thread> threads = new List<Thread>();
foreach (cpsComms.cpsSerial ser in availPorts)
{
    Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
    t.Start((object)ser);//start thread and pass it the port
    threads.Add(t);
}
foreach(var thread in threads)
{
    thread.Join();
}
private ManualResetEvent manual = new ManualResetEvent(false);
void Main(string[] args)
{
    AutoResetEvent[] autos = new AutoResetEvent[availPorts.Count];

    manual.Set();

    for (int i = 0; i < availPorts.Count - 1; i++)
        {

        AutoResetEvent Auto = new AutoResetEvent(false);
        autos[i] = Auto;

        Thread t = new Thread(() => lookForValidDev(Auto, (object)availPorts[i]));
        t.Start();//start thread and pass it the port  

    }
    WaitHandle.WaitAll(autos);
    manual.Reset();

}


void lookForValidDev(AutoResetEvent auto, object obj)
{
    try
    {
         manual.WaitOne();
         // do something with obj 
    }
    catch (Exception)
    {

    }
    finally
    {
        auto.Set();
    }


} 
private ManualResetEvent manual=新的ManualResetEvent(错误);
void Main(字符串[]args)
{
AutoResetEvent[]autos=新的AutoResetEvent[availPorts.Count];
手动设置();
for(int i=0;ilookForValidDev(自动,(对象)可用端口[i]);
t、 Start();//启动线程并将其传递到端口
}
WaitHandle.WaitAll(自动);
手动复位();
}
void lookForValidDev(自动重置事件自动,对象对象对象)
{
尝试
{
manual.WaitOne();
//用obj做点什么
}
捕获(例外)
{
}
最后
{
auto.Set();
}
} 

您可以使用倒计时闩锁:

public class CountDownLatch
{
    private int m_remain;
    private EventWaitHandle m_event;

    public CountDownLatch(int count)
    {
        Reset(count);
    }

    public void Reset(int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException();
        m_remain = count;
        m_event = new ManualResetEvent(false);
        if (m_remain == 0)
        {
            m_event.Set();
        }
    }

    public void Signal()
    {
        // The last thread to signal also sets the event.
        if (Interlocked.Decrement(ref m_remain) == 0)
            m_event.Set();
    }

    public void Wait()
    {
        m_event.WaitOne();
    }
}

最简单、最安全的方法是使用倒计时事件。请参见。

严格地说,这只是一个旁注,并不是您询问过它,但您可以在线程上设置IsBackground=true,这样在退出应用程序时就不会让它阻止主线程。auto.Set()应该位于finally blockAh中,我不知道如果线程已终止,连接将返回。谢谢你的更正。这不是作为倒计时事件包含在.NET中吗?这是一个很好且简单的解决方案。但在我的例子中,System.Threading.Thread.Join()在具有高排他时间值的检测分析报告中可见。尽管如此,这是一个非常好的方法。
public class CountDownLatch
{
    private int m_remain;
    private EventWaitHandle m_event;

    public CountDownLatch(int count)
    {
        Reset(count);
    }

    public void Reset(int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException();
        m_remain = count;
        m_event = new ManualResetEvent(false);
        if (m_remain == 0)
        {
            m_event.Set();
        }
    }

    public void Signal()
    {
        // The last thread to signal also sets the event.
        if (Interlocked.Decrement(ref m_remain) == 0)
            m_event.Set();
    }

    public void Wait()
    {
        m_event.WaitOne();
    }
}
void StartThreads
{
    CountDownLatch latch = new CountDownLatch(availPorts.Count);

    foreach (cpsComms.cpsSerial ser in availPorts)
    {
        Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));

        //start thread and pass it the port and the latch
        t.Start((object)new Pair(ser, latch));

    }

    DoSomeWork();

    // wait for all the threads to signal
    latch.Wait();

    DoSomeMoreWork();
}

// In each thread
void NameOfRunMethod
{
    while(running)
    {
        // do work
    }

    // Signal that the thread is done running
    latch.Signal();
}