Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么新线程可以访问UI?_C#_Windows Runtime_Windows Store Apps_Async Await - Fatal编程技术网

C# 为什么新线程可以访问UI?

C# 为什么新线程可以访问UI?,c#,windows-runtime,windows-store-apps,async-await,C#,Windows Runtime,Windows Store Apps,Async Await,以以下方法为例: private async void F() { button.IsEnabled = false; await Task.Delay(1000); button.IsEnabled = true; } 在这种情况下,任何以await开头的代码总是出现在另一个线程(编辑:错误)上,该线程可能无法访问UI线程,类似于桌面应用程序。在类似情况下,我记得有一个例外,例如: 应用程序调用了为不同线程封送的接口 但是,该示例不会触发任何异常。这是预期的吗?我能可

以以下方法为例:

private async void F()
{
    button.IsEnabled = false;
    await Task.Delay(1000);
    button.IsEnabled = true;
}
在这种情况下,任何以
await
开头的代码总是出现在另一个线程(编辑:错误)上,该线程可能无法访问UI线程,类似于桌面应用程序。在类似情况下,我记得有一个例外,例如:

应用程序调用了为不同线程封送的接口


但是,该示例不会触发任何异常。这是预期的吗?我能可靠地编写这样的代码吗?

在UI线程上运行的代码具有
同步上下文。您可以通过打印
SynchronizationContext.Current
看到这一点。在等待某个内容之前,捕获该上下文;在等待之后,代码在该上下文上恢复,从而确保继续在UI线程上运行

要获取所引用的行为,如果继续在
ThreadPool
线程上运行,则可以使用
ConfigureAwait(false)
禁用
SynchronizationContext
捕获:

此代码将引发您期望的异常

这是预期的吗?我能可靠地编写这样的代码吗

是的,是的。默认情况下,使用async await的代码将“做正确的事情”。但是,如果您确实希望将某些内容卸载到
线程池
线程中,则可以使用
任务。运行

任何从wait开始的代码总是出现在另一个线程上(非UI线程,对吗?)

不,一点也不<代码>等待
不会启动其他线程。如果你觉得这句话令人困惑,我有一个可能会有所帮助的建议


wait
将要做的是将方法的剩余部分安排为在异步操作完成后继续运行(在这种情况下,异步操作只是一个计时器触发)。默认情况下,
wait
将捕获一个“上下文”,它是
SynchronizationContext.Current
(或者,如果它是
null
,则上下文是
TaskScheduler.Current
)。在这种情况下,有一个UI
SynchronizationContext
,它确保
async
方法的其余部分将在UI线程上运行。

我想我错了,
wait
之外的代码在不同的线程上运行,因此它被发布到
SynchronizationContext
,由UI线程使用?@Avenicci任务后的继续。延迟完成被发布到SC,以确保它在UI线程上运行。可以肯定的是,
Task.Delay
是否启动新线程?我记得有人这样争论的一条线索。@Avenicci:没有。它只是启动了一个计时器。上次我检查时,每个应用程序都有一个线程,可以同时处理所有计时器。当计时器完成时,它的回调在线程池线程上被调用,线程池线程只用于完成从
Task.Delay
返回的
Task
。但是没有创建新线程。如果
Task.Delay
使用相同的线程,异步方法如何直接终止?@Avenicci:调用线程不终止-它只是返回。
private async void FooAsync()
{
    button.IsEnabled = false;
    await Task.Delay(1000).ConfigureAwait(false);
    button.IsEnabled = true;
}