英文:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论