2013-11-01 16 views
2

我最近更改了一些代碼以異步,使用async/await模式。同步上下文沒有通過async/await保存?

該代碼現在創建一個例外:

private async void Refresh(object stateInfo) 
{ 
    await Task.Factory.StartNew(HydrateServerPingDtoList); 
    // more code here 
} 

private void HydrateServerPingDtoList() 
{ 
    // more code here. 
    // Exception occurs on this line: 
    this._serverPingDtoList.Add(new ServerPingDto() { ApplicationServer = server }); 
} 

例外:

這種類型的CollectionView不支持從一個線程從調度線程不同其 SourceCollection變化。

_serverPingDtoList是WPF綁定屬性的後臺字段。既然我認爲async-await保存了同步上下文,爲什麼我會得到這個錯誤呢?

+0

我不認爲這會在明確的'StartNew'中做到這一點。它會做什麼是保留生成的延續的上下文,以便'//更多代碼在這裏' – vcsjones

+1

你的簽名不應該返回一個'任務'嗎? –

回答

11

await在其自己的async方法中恢復SynchronizationContext。它不會將它傳播到通過StartNew開始的後臺線程。

請注意,StartNew不應在async代碼中使用;我在我的博客上寫了explain why in detail。您應該使用Task.Run來執行CPU綁定代碼。

但是,任何UI更新(包括數據綁定屬性的更新)都應在UI線程上完成,而不是在後臺任務上完成。所以,假設你的HydrateServerPingDtoList實際上是CPU綁定的,你可以這樣做:

private ServerPingDto HydrateServerPingDtoList() 
{ 
    // more code here. 
    return new ServerPingDto() { ApplicationServer = server }; 
} 

private async Task Refresh(object stateInfo) 
{ 
    var serverPingDto = await Task.Run(() => HydrateServerPingDtoList()); 
    this._serverPingDtoList.Add(serverPingDto); 
    // more code here 
}