What's the difference between the first method that runs Task.Run and the one which doesn't run Task.Run?

huangapple go评论65阅读模式
英文:

What's the difference between the first method that runs Task.Run and the one which doesn't run Task.Run?

问题

The listenForClients1 method uses Task.Run to execute its content on a different thread, which prevents it from blocking the main thread. On the other hand, the listenForClients2 method does not use Task.Run, so it runs on the main thread, causing it to block.

Task.Run is used to offload work to a separate thread, ensuring that it doesn't interfere with the main thread's responsiveness. In your code, listenForClients1 uses Task.Run, making it non-blocking, while listenForClients2 runs on the main thread, which blocks it.

If you want the task to run on a different thread to avoid blocking the main thread, you should use Task.Run as demonstrated in listenForClients1.

英文:

The listenForClients1 method doesn't block the main thread but the listenForClients2 does. Why is there a difference here? Both tasks seems to be executing but the second doesn't begin working on a new thread.

I want the task to run on a different thread but I'm very confused to why I need to call the Task.Run and what that specific static method does differently that makes the task perform on a different thread?

            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"; });
        }

Thank you for any answers! Best regards, Lukas.

I tried different methods and expected them both to not block the main thread.

答案1

得分: 2

The first one hands off the code to a threadpool thread and will not block. 第一个函数将代码交给线程池线程,不会阻塞。

The second function has no handling whatsoever for asynchronicity, so it will block. 第二个函数对异步性没有任何处理,因此会阻塞。

Invoke was not necessary in the second function, and it's unclear why you needed it. 在第二个函数中不需要使用Invoke,也不清楚为什么需要它。

But neither of these options are correct. 但这两个选项都不正确。

What you should do is use await Task.Delay instead, rather than making a blocking Thread.Sleep call. 你应该使用await Task.Delay,而不是进行阻塞的Thread.Sleep调用。

You also need to call the function using await, otherwise dragons may jump out your screen. 你还需要使用await来调用函数,否则可能会出现屏幕上跳出龙。

Note that there is a slight difference in logic here: because we passed the token to Task.Delay we may get cancelled in the middle of it, whereas the original code will not break out until the end of the timer. To avoid that behavior you can do await Task.Delay(1000); 请注意,这里的逻辑略有不同:因为我们将令牌传递给了Task.Delay,所以我们可能会在其中间被取消,而原始代码将一直执行到计时器结束。为了避免这种行为,你可以使用await Task.Delay(1000);

英文:

The first one hands off the code to a threadpool thread and will not block. The second function has no handling whatsoever for asynchonicity, so it will block. Invoke was not necessary in the second function, and it's unclear why you needed it.

But neither of these options are correct. What you should do is use await Task.Delay instead, rather than making a blocking Thread.Sleep call.

You also need to call the function using await, otherwise dragons may jump out your screen.

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);

Note that there is a slight difference in logic here: because we passed the token to Task.Delay we may get cancelled in the middle of it, whereas the original code will not break out until the end of the timer. To avoid that behaviour you can do await Task.Delay(1000);

huangapple
  • 本文由 发表于 2023年5月7日 18:00:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定