【发布时间】:2020-01-31 21:01:04
【问题描述】:
在 Stephen Cleary 的文章“Async and Await”中,据说要在线程池上运行 awaitable,您需要在该 awaitable 上调用 ConfigureAwait(false)。这在某种程度上与我的经验不符。我创建了一个小应用程序,我认为它证明无需调用 ConfigureAwait 即可在单独的线程上执行 awaitable。
我使用 log4net 工具进行日志记录。 在不使用“ConfigureAwait”方法的情况下,awaitable 在不同的线程 ([3]) 上执行,然后是 UI ToolStripButton1_Click 调用(UI 线程是 [1],池线程是 [3] - 代码和日志输出附在下面)。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public Form1()
{
InitializeComponent();
}
private async void ToolStripButton1_Click(object sender, EventArgs e)
{
await TestAsync();
}
private async Task TestAsync()
{
log.Info("Button clicked before Run Sleep task. Expect to run this from UI thread");
Task t = Task.Run( () =>
{
log.Info("Button clicked from Run before Sleep. Expect to run this from a pool thread");
Thread.Sleep(1000 * 5);
log.Info("Button clicked from Run after Sleep. Expect to run this from a pool thread");
return true;
});//.ConfigureAwait(continueOnCapturedContext: false);
await t;
log.Info("Button clicked after Run. Expect to run this from UI thread"); // Expect to run this in UI thread
}
}
}
日志输出如下:
2020-01-31 19:57:14,805 [1] 信息 WindowsFormsApp1.Form1[MoveNext] - 在运行睡眠任务之前单击了按钮。期望从 UI 线程运行它
2020-01-31 19:57:14,835 [3] 信息 WindowsFormsApp1.Form1[b__3_0] - 从睡眠前运行中单击的按钮。期望从池线程中运行它
2020-01-31 19:57:19,837 [3] 信息 WindowsFormsApp1.Form1[b__3_0] - 从“睡眠后运行”中单击的按钮。期望从池线程中运行它
2020-01-31 19:57:19,839 [1] 信息 WindowsFormsApp1.Form1[MoveNext] - 运行后单击按钮。期望从 UI 线程运行它
我没有调用 ConfigureAwait(false) 并且 awaitable 是在线程池上执行的。
【问题讨论】:
-
ConfigureAwait 是为了继续等待,它应该在哪里继续执行。
-
默认情况下
await捕获当前同步上下文并在其上恢复执行(在您的情况下为 UI 线程)。ConfigureAwait(false)禁用此功能,并在线程池上继续执行。Task.Run将始终在线程池线程上运行(它与 UI 线程不同)。您可能混合了异步代码执行及其恢复后的继续 -
在我的理解中,
ConfigureAwait(false)不会影响运行 awaitable 的上下文,它会影响 continuation 的上下文(即await之后的所有内容) . -
你指的文章是8年前的。
标签: c# multithreading asynchronous async-await