winforms 运行Task.Run的第一个方法和不运行Task.Run的方法有什么区别?

cedebl8k  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(233)

listenForClients 1方法不会阻塞主线程,但listenForClients 2会阻塞。为什么会有区别呢?两个任务似乎都在执行,但第二个任务没有开始在新线程上工作。
我想让任务在不同的线程上运行,但我很困惑为什么我需要调用Task.Run,以及那个特定的静态方法做了什么不同的事情,使任务在不同的线程上执行?

if(temp.Name == "buttonStart" && int.TryParse(textBoxPort.Text, out port)) //Startar servern...
            {
                #region Btn appearance:

                temp.Enabled = false;
                buttonStop.Enabled = true;
                buttonStart.BackColor = Color.FromArgb(108, 156, 67);
                buttonStop.BackColor = Color.FromArgb(212, 101, 78);

                #endregion

                listeningTokenSource = new CancellationTokenSource();
                var token = listeningTokenSource.Token;

                listenForClients1(token);

                Invoke(() => { richTextBoxLog.Text += "Testing"; });
            }
            else if(temp.Name == "buttonStop") //Stoppar servern...
            {
                #region Btn appearance:

                temp.Enabled = false;
                buttonStart.Enabled = true;
                buttonStart.BackColor = Color.FromArgb(145, 207, 91);
                buttonStop.BackColor = Color.FromArgb(156, 76, 59);

                #endregion

                listeningTokenSource.Cancel(); //Stoppar processen.
            }
        }

        private async Task listenForClients1(CancellationToken token)
        {
            Task.Run(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Invoke(() => { richTextBoxLog.Text += "b"; });
                }
                Invoke(() => { richTextBoxLog.Text += "Done"; });
            });
        }

        private async Task listenForClients2(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                Thread.Sleep(1000);
                Invoke(() => { richTextBoxLog.Text += "b"; });
            }
            Invoke(() => { richTextBoxLog.Text += "Done"; });
        }

谢谢你的回答!问候你卢卡斯
我尝试了不同的方法,并希望它们都不会阻塞主线程。

6tr1vspr

6tr1vspr1#

第一个线程将代码交给一个线程池线程,不会阻塞。第二个函数没有任何异步处理,所以它会阻塞。Invoke在第二个函数中是不必要的,不清楚为什么需要它。

**但这两个选项都不正确。**您应该 * 做的是使用await Task.Delay,而不是进行阻塞Thread.Sleep调用。

您还需要使用await调用该函数,否则可能会跳出屏幕。

private async Task listenForClients3(CancellationToken token)
{
    try
    {
        while (!token.IsCancellationRequested)
        {
            await Task.Delay(1000, token);
            richTextBoxLog.Text += "b";
        }
    }
    catch (OperationCanceledException)
    { //
    }
    richTextBoxLog.Text += "Done";
}
await listenForClients3(someToken);

请注意,这里的逻辑略有不同:因为我们将令牌传递给Task.Delay,所以我们可能会在中间被取消,而原始代码直到计时器结束才会中断。要避免这种行为,可以执行await Task.Delay(1000);

相关问题