【问题标题】:C# wait for other threadsC#等待其他线程
【发布时间】:2014-10-27 13:17:40
【问题描述】:

我还没有找到能够适应我的问题的答案。

所以情况是这样的: 我需要测试 12 台网络摄像机的功能,它们都在做同样的工作。 所以,我正在启动 12 个线程,连接到摄像头。

每个线程都在发送激活命令,然后等待 10 秒等待响应,预计不会出现。

在这 10 秒之后,线程应该进入等待状态并通知主线程。

一旦所有 12 个线程都处于等待状态,就会通过串行连接发送命令,线程应该继续工作。现在他们应该会收到答复。

到目前为止,我已经启动了 12 个线程,但我不知道此时如何让它们同步。

有什么帮助吗?

到目前为止的代码:

Dictionary<String, Thread> tl = new Dictionary<String, Thread>();
Thread t;
foreach (String ip in this.ips) {
    t = new Thread(new ParameterizedThreadStart(camWorker));
    tl.Add(ip, t);
    tl[ip].Start();
}

但如果需要,可以重建它以为每个线程创建单独的类实例。

【问题讨论】:

  • 为了适应多线程你已经做了哪些工作?即一段代码?
  • 更新了问题
  • 您是在寻找一种方法来重新唤醒线程还是只是让它们保持同步?
  • 我会简单地使用计数器。每次启动 Task 时将其递增,激活完成时递减(如果需要结果,则为正或负结果 - 存储它)。一旦它是0,您就知道所有任务都已完成。见Interlocked.Increment。
  • 只使用任务/异步方法,除非有真正的原因,否则不要打扰线程和同步原语(早期版本的 .NET 和与现有线程代码的一致性可能是坚持使用的两个主要原因线程)。

标签: c# multithreading


【解决方案1】:

您可以使用重置事件。为每个线程创建一个重置事件,并在最后等待所有 12 个重置事件完成。

例子:

var resetEvents = new List<AutoResetEvent>();
for (int i = 0; i < 12; i++)
{
   var re = new AutoResetEvent(false);
   resetEvents.Add(re);

   ThreadPool.QueueUserWorkItem(w =>
   {
       var threadReset = w as AutoResetEvent;
       var random = new Random();
       try
       {
          // do something.
          Thread.Sleep(random.Next(100, 2000));
       }
       catch (Exception ex)
       {
          // make sure you catch exceptions and release the lock.
          // otherwise you will get into deadlocks
       }

       // when ready:
       Console.WriteLine("Done thread " + Thread.CurrentThread.ManagedThreadId);
       threadReset.Set();
    }, re);
}

// this bit will wait for all 12 threads to set
foreach (AutoResetEvent resetEvent in resetEvents)
{
   resetEvent.WaitOne();
}

// At this point, all 12 of your threads have signaled that they're ready.

【讨论】:

    【解决方案2】:
    bool[] timeout = new bool[12];
    bool waitForSignal = true;
    oneof12()
    {
        while(true)
        {
            if(receivedatabeforetimeout())
            {
    
    
            }
            else
                timeout[0] = true;
            while(waitForSignal)
                Thread.Sleep(500);
        }
    }
    
    watcherThread()
    {
        bool allTimeout = true;
        for(int a = 0; a<12;a++)
            if(!timeout[0])
                allTimeout = false;
    
        if(allTimeout)
        {
            for(int a = 0; a<12;a++)
                timeout[a] = false;
            waitForSignal = false;
        }
    Thread.Sleep(200);
    }
    

    在你的情况下这样的事情会起作用吗?如果超时,12 个线程中的每一个都将 bool 数组中的索引设置为 true。观察者线程检查 bool 数组是否所有 12 个都已超时,如果有,则将 waitForSignal 标志设置为 true,这会导致 12 个线程退出 while 循环并再次等待数据

    【讨论】:

      【解决方案3】:

      这听起来像是一个很好的任务案例。从本质上讲,您可以等待 12 个任务,每个任务检查一个摄像头的状态。这样做的好处是您不必管理独立的线程。

      using System.Linq;
      using System.Threading.Tasks;
      
      ...
      
      var Tasks = this.ips.Select(ip => Task.Run(() => Check(ip))).ToArray();
      
      Task.WaitAll(Tasks);
      
      //inspect Task.Result to display status and perform further work
      

      请注意,您的Check 方法可以返回一个结果,然后可以通过Task.Result 访问该结果。 Task.WaitAll 阻塞当前线程,直到所有任务都运行完成。

      不清楚您将从什么调用此代码,但如果合适,您也可以使用 C# 的 async 功能。

      【讨论】:

        【解决方案4】:

        我建议为此使用任务。

        List<Task> tasks = new List<Task>();
        
        for (int i=0; i<10; i++)
        {
            tasks.Add(Task.Factory.StartNew(() => DoSomething());
        }
        
        Task.WaitAll(tasks);
        

        这将使所有任务在后台并行运行,并等待它们全部完成后再继续。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-21
          • 1970-01-01
          • 1970-01-01
          • 2023-03-21
          • 2023-03-07
          • 1970-01-01
          • 2019-08-27
          • 1970-01-01
          相关资源
          最近更新 更多