为什么我不能递归调用Worker_DoWork函数?

时间:2020-05-10 23:02:41

标签: c# sockets networking tcp

我使用Sytem.Net.Sockets在c#中有一个TCP服务器和客户端。我的工作程序功能如下

   private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        byte[] buffer = new byte[1];
        socket.Receive(buffer);
        chatTextBox.Text = buffer[0].ToString();        
    }

我在创建服务器后调用此命令,一旦它收到来自客户端的消息,便将其写在屏幕上并停止。我的问题是,我希望它在最后再次调用自身,以便它等待另一条消息显示。如果我只是添加worker.RunWorkerAsync();在底部,它不起作用,但是,如果我仅从另一个按钮调用它,它将起作用并接收并编写消息。

1 个答案:

答案 0 :(得分:1)

BackgroundWorker围绕线程“包装”,并帮助您处理所有管线。对于多任务处理而言,这是一种过时的方法,您不应再在生产性代码中使用它。但是,它也是我了解的多任务处理的最佳“训练轮”。

您的基本方法存在缺陷。 BGW不允许这样做,实际上只是在帮助您学习需要学习的东西。您的代码中的错误列表:

  • 您正在直接在DoWork中访问GUI元素。不要那样做。仅在ReportProgress和RunWorker完成的事件中编写UI。这是general Multithreading rule,由BGW的设计提供帮助。
  • 您正在尝试在线程完成之前重新启动它。如果您想重新启动它,RunWorkerCompleted将是正确的地方
  • 但是,对于
  • 来说,BackgroundWorker的核心是一个半无限循环更明智。一直运行到取消的东西。通常用报告分发信息不是一个好主意,但在这种情况下,这是我最好的主意。

我只能给我的另一件事是我以前的BGW示例代码:

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
    if (!bgwPrim.IsBusy)
    {
        //Prepare ProgressBar and Textbox
        int temp = (int)nudPrim.Value;
        pgbPrim.Maximum = temp;
        tbPrim.Text = "";

        //Start processing
        bgwPrim.RunWorkerAsync(temp);
    }
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
    if (bgwPrim.IsBusy)
    {
        bgwPrim.CancelAsync();
    }
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
    int highestToCheck = (int)e.Argument;
    //Get a reference to the BackgroundWorker running this code
    //for Progress Updates and Cancelation checking
    BackgroundWorker thisWorker = (BackgroundWorker)sender;

    //Create the list that stores the results and is returned by DoWork
    List<int> Primes = new List<int>();


    //Check all uneven numbers between 1 and whatever the user choose as upper limit
    for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
    {
        //Report progress
        thisWorker.ReportProgress(PrimeCandidate);
        bool isNoPrime = false;

        //Check if the Cancelation was requested during the last loop
        if (thisWorker.CancellationPending)
        {
            //Tell the Backgroundworker you are canceling and exit the for-loop
            e.Cancel = true;
            break;
        }

        //Determin if this is a Prime Number
        for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
        {
            if (PrimeCandidate % j == 0)
                isNoPrime = true;
        }

        if (!isNoPrime)
            Primes.Add(PrimeCandidate);
    }

    //Tell the progress bar you are finished
    thisWorker.ReportProgress(highestToCheck);

    //Save Return Value
    e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pgbPrim.Value = pgbPrim.Maximum;
    this.Refresh();

    if (!e.Cancelled && e.Error == null)
    {
        //Show the Result
        int[] Primes = (int[])e.Result;

        StringBuilder sbOutput = new StringBuilder();

        foreach (int Prim in Primes)
        {
            sbOutput.Append(Prim.ToString() + Environment.NewLine);
        }

        tbPrim.Text = sbOutput.ToString();
    }
    else 
    {
        tbPrim.Text = "Operation canceled by user or Exception";
    }
}
#endregion