在许多博客,教程和MSDN中,我可以读取从非UI线程访问UI元素是不可能的 - 好的,我会得到未经授权的异常。为了测试它,我已经写了一个很简单的例子:在异步任务和UI线程中引发PropertyChanged
// simple text to which TextBlock.Text is bound
private string sample = "Starting text";
public string Sample
{
get { return sample; }
set { sample = value; RaiseProperty("Sample"); }
}
private async void firstButton_Click(object sender, RoutedEventArgs e)
{
await Job(); // asynchronous heavy job
commands.Add("Element"); // back on UI thread so this should be ok?
}
private async Task Job()
{
// I'm not on UI Thread ?
await Task.Delay(2000); // some other job
Sample = "Changed"; // not ok as not UI thread?
commands.Add("Element from async"); // also not ok?
}
我正运行的异步任务,在任务我想:更改我的财产(这将提高的PropertyChanged),并添加元素的ObservableCollection。由于它运行异步,我不应该能够这样做,但我没有例外,代码工作正常。因此我的疑惑和误解:
- 为什么我不能例外?
- 可以在异步任务中提高PropertyChanged吗?
- 可以在异步任务中修改ObservableCollecition,或者我应该返回Task并获得结果后修改Observable - 清除它并填充它?
- 当我在任务上的UI线程和什么时候没有?
- 上面的代码在
firstButton_Click
是否可以在等待任务后管理UI元素?我总是回到UI线程?
为了测试它更多,我已经把在其他线程我的财产变化和收集修改:
System.Threading.Timer newThreadTimer = new System.Threading.Timer((x) =>
{
Sample = "Changed"; // not UI thread - exception
commands.Add("Element from async"); // not UI thread - exception
}, null, 1000, Timeout.Infinite);
在上面的代码中我的想法是好的 - 只是第一或第二线,我得到一个异常后。但是第一个代码是什么?我的任务在UI线程上运行只是运气好吗?
我怀疑这是非常基本的事情和我的误解,但我需要一些澄清,因此这个问题。
我会+1这个如果不是这个声明:*“任务并行库使用'TaskScheduler'隐式(或明确地...)捕获当前的'SynchronizationContext' ...“*这是不正确的'await'延续:http://stackoverflow.com/q/23071609/1768303 – Noseratio
长答案(谢谢你),但我一些疑虑:1.看看我的Job是以异步方式运行的[等待Job();'Click) - 这样捕获的UI上下文是不是内部之前和之后?2.我很困惑从同一个线程返回等待 - for例如[我无法在Mutex内部等待](http://stackoverflow.com/q/23153155/2681948),因此在返回'捕获的上下文可能意味着任何线程池线程'。3.如果它可以将属性从async Task(在不同的线程上)改变,然后为什么不使用定时器? – Romasz
@Romasz你通过'asynchronous' /'synchronous'和'concurrent'的不同概念混淆了相关的问题,你写的所有代码都是单线程,这意味着你没有问题,使用'async' /'await'的初学者错误是想,对...我们重新异步,这意味着线程是正确的?线程意味着“并发”,在过去这是实现“异步”的唯一方法。 – Aron