【问题标题】:convert starting dedicated threads to threadpool将启动专用线程转换为线程池
【发布时间】:2013-10-11 11:42:16
【问题描述】:

使用 ThreadPool 实现以下代码的等效方式是什么:

Receiver 是我正在实例化的一个类

foreach (MobileAccounts MobileAccount in ReceiverAccounts)
{                        
    Receiver rec = new Receiver();
    ThreadStart starterParameters = delegate { rec.StartListener(MobileAccount); };
    Thread FeedbackThread = new Thread(starterParameters);
    FeedbackThread.Name = MobileAccount.FriendlyName;

    FeedbackThread.Start();                                                                                           
}

【问题讨论】:

  • 哪个运行时版本,可以使用Task Parallel Library吗?
  • 我正在使用安装了 4.5 的 Visual Studio 2012

标签: c# multithreading


【解决方案1】:

如果您切换到 ThreadPool,您不一定能够命名线程,但是您可以使用 Task Parallel 库来实现您的目标。 TPL

一种方法是

foreach (MobileAccounts MobileAccount in ReceiverAccounts) {
  Receiver rec = new Receiver();
  Task.Run(() => rec.StartListener(MobileAccount));
}

甚至使用 Parallel.ForEach

Parallel.ForEach(ReceiverAccounts, 
                 MobileAccount => new Receiver().StartListener(MobileAccount));

【讨论】:

  • 这些都可以让我也处理一个特定的线程吗?
  • @BossRoss 你是什么意思?不应终止或释放 ThreadPool 中的线程,该线程需要被重用。
  • @BossRoss 你是在说清理还是远程杀死听众?
  • 被调用的方法将是一个长时间运行的方法。如果特定线程内出现问题,我需要终止该特定线程并重新启动它。
  • 一个线程池(以及扩展的TPL)使用一个常用线程池来执行工作负载(即方法)。如果 workload 失败,则再次提交。您没有也不应该要求对实际线程进行任何访问。至于使用 TPL 重试,请查看 this conversation 以了解使用 Tasks 或 async\await 关键字的方法
【解决方案2】:
  var tokenSource2 = new CancellationTokenSource();

  foreach (MobileAccounts MobileAccount in ReceiverAccounts)
  {
    var rec = new Receiver();
    var ct = tokenSource2.Token;
    Task.Factory.StartNew(() => this.DoWorkEventArgs(rec, ct));
  }

 // Anywhere outside you can call tokenSource2.Cancel();


 private void DoWorkEventArgs(Receiver rec, CancellationToken ct)
 {
   // Were we already canceled?
   ct.ThrowIfCancellationRequested();

   bool moreToDo = true;
   while (moreToDo)
   {
       // Poll on this property if you have to do 
       // other cleanup before throwing. 
       if (ct.IsCancellationRequested)
       {
         // Clean up here, then...
         ct.ThrowIfCancellationRequested();
       }
    }
 }

【讨论】:

    【解决方案3】:

    回答我原来的问题:

    foreach (MobileAccounts MobileAccount in ReceiverAccounts)
    {
        Receiver rec = new Receiver();
    
        ThreadPool.QueueUserWorkItem(delegate { rec.StartListener(MobileAccount); }, null);                    
    
    
    }
    

    【讨论】:

    • 如果您正在启动的任务是长时间运行的,则存在锁定线程池的风险。如果您有足够多的帐户,您的某些任务甚至可能无法运行。线程池设计用于相对较短的任务。
    • 在这种情况下,线程数将是一个已知常数。最多8个线程。谢谢你的信息。
    猜你喜欢
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    • 2012-12-28
    • 2018-10-02
    • 2016-09-04
    • 2015-12-08
    相关资源
    最近更新 更多