后台工作者窃取主线程

Background worker stealing main thread

所以我不能肯定地说这就是问题所在,但我只是肯定它是。我有一个要拨打的 IVR 电话记录集。我将每个数据放在一个并发队列中,并启动 5 个后台工作人员从队列开始工作。然而,打了2个电话之后,电话就没有了,直到一个人挂断电话,然后就转到了3、4、5等号码。这段代码有什么问题吗?

似乎后台工作人员正在阻止彼此调用相同的方法...?这可能吗?

private ConcurrentQueue<DataTable> _ivrCallsQueue = new ConcurrentQueue<DataTable>();

private List<BackgroundWorker> _ivrCallers = new List<BackgroundWorker>();

public overrid void Process()
{
 foreach(DataRow row in _tblRecordsToProcess.Rows)
    {
       _workingActionItem = actionItemDAL.GetActionItemFromId(Convert.ToInt32(row["FNActionItemId"].ToString()));

        var workingActionItemsTable = actionItemDAL.GetActionItemParamValues(Convert.ToInt32(row["FNActionItemId"].ToString()));

       ivrCallsQueue.Enqueue(workingActionItemsTable);
    }

    StartCalls();

  while (_ivrCallers.Count != 0)
  {
      testurls = testurls;
  }
}

private void StartCalls()
{
    int maxLines = 5;

    if (_ivrCallsQueue.Count < maxLines)
    {
        maxLines = _ivrCallsQueue.Count;
    }

   for (int i = 0; i < maxLines; i++)
   {
       DataTable workingCall = new DataTable();

       _ivrCallsQueue.TryDequeue(out workingCall);

       BackgroundWorker ivrCaller = new BackgroundWorker();

       _ivrCallers.Add(ivrCaller);

            ivrCaller.DoWork += delegate(object sender, DoWorkEventArgs e)
          {
                RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
                _ivrCallers.Remove(ivrCaller);
            };

            ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);

            ivrCaller.RunWorkerAsync();
   }
}

private void bw_AnalyzeResults(object sender, RunWorkerCompletedEventArgs e)
{
    DataTable workingCall = new DataTable();

    if (_ivrCallsQueue.Count != 0)
    {
        _ivrCallsQueue.TryDequeue(out workingCall);

        BackgroundWorker ivrCaller = new BackgroundWorker();

        ivrCaller.DoWork += delegate(object completeSender, DoWorkEventArgs completeArgs)
        {
            RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
            _ivrCallers.Remove(ivrCaller);
        };

        ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);

        ivrCaller.RunWorkerAsync();
    }
    else
    {

    }
}

private void RequestIVR(DataTable workingTable,int fnActionItemID)
{
     var urlRequest = "http://uccx_http_trigger:9080/test?strTestMode=1&strTaskID=" + fnActionItemID;

    var webClient = new WebClient { UseDefaultCredentials = true, Proxy = WebRequest.DefaultWebProxy };
    DecodeResponseType(GetValueFromElement("Response Code was&nbsp;", webClient.DownloadString(urlRequest)));
  }

看起来 bw_AnalyzeResults 做的事情与 StartCalls() 做的几乎一样。换句话说,当后台工作人员完成其工作时,您立即将相同的工作排入队列以永远递归地再次发生?

从表面上看,您希望 bw_AnalyzeResults 分析调用您的网络服务返回的结果。这不是目前正在发生的事情。

以下取自 bw_AnalyzeResults 事件处理程序的代码正在安排后台作业并使其自身处理 RunWorkerCompleted 事件。所以,大概软件一直在不停地执行 bw_AnalyzeResults 直到你终止进程?

private void bw_AnalyzeResults(object sender, RunWorkerCompletedEventArgs e)
{
    ivrCaller.DoWork += delegate(object completeSender, DoWorkEventArgs completeArgs)
    {
        RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
        _ivrCallers.Remove(ivrCaller);
    };
    ivrCaller.RunWorkerCompleted += (bw_AnalyzeResults);
}

这将生成最多五个线程,每个线程都尝试从队列中拉出下一个项目并进行处理。如果队列为空,尝试将失败,线程将简单地退出:

    private List<System.Threading.Thread> Threads = new List<System.Threading.Thread>();
    private ConcurrentQueue<DataTable> _ivrCallsQueue = new ConcurrentQueue<DataTable>();

    private void StartCalls()
    {
        int maxLines = Math.Min(5 , _ivrCallsQueue.Count);
        for (int i = 0; i < maxLines; i++ )
        {
            System.Threading.Thread T = new System.Threading.Thread(delegate()
            {
                DataTable workingCall;
                while (_ivrCallsQueue.TryDequeue(out workingCall))
                {
                    RequestIVR(workingCall, Convert.ToInt32(workingCall.Rows[2][0].ToString()));
                }
            });
            Threads.Add(T);
            T.Start();
        }
    }

线程将保持 运行,直到处理完所有项目。