Von dem, was ich über die Async CTP mit dem asynchronen Ereignismuster gesehen habe, sollte der Code, den ich hier habe, gut funktionieren, mit var result1 = await tcs1.Task
blockiert bis clientGetFileList.GetCompleted
feuert. Was jedoch passiert, ist, dass ich zurück zu GetRestoreStream geprallt bin, unter return GetRestoreStreamAwait().Result
, die niemals zurückkommt - stattdessen stört mich meine App ziemlich.Verwendung von async/await mit Live SDK
Kann mir bitte jemand erklären, was ich falsch mache?
protected override Stream GetRestoreStream()
{
if (SkyDriveFolderId != null)
return GetRestoreStreamAwait().Result;
return Stream.Null;
}
private async Task<Stream> GetRestoreStreamAwait()
{
LiveConnectClient clientGetFileList = new LiveConnectClient(_session);
TaskCompletionSource<LiveOperationCompletedEventArgs> tcs1 = new TaskCompletionSource<LiveOperationCompletedEventArgs>();
EventHandler<LiveOperationCompletedEventArgs> d1 = (o, e) => { tcs1.TrySetResult(e); };
clientGetFileList.GetCompleted += d1;
clientGetFileList.GetAsync(SkyDriveFolderId + "/files");
var result1 = await tcs1.Task;
clientGetFileList.GetCompleted -= d1;
// ... method continues for a while
}
Update: Dieses Stück Code scheint durch die ganze Art und Weise zu bewegen, aber task.Start()
weg wirft ein InvalidOperationException
so dass ich eigentlich nie den Strom am Ende bekommen. Wenn man es in einen try/catch wickelt, ändert sich auch nichts - ohne die try/catch wird die InvalidOperationException weiter oben im Stack abgefangen, während der Vorgang glücklicherweise ohne Wissen darüber abläuft, dass sein Ergebnis niemals verwendet wird; mit ihm task.Result
friert die Dinge genauso sicher wie der Code oben.
protected override Stream GetRestoreStream()
{
if (SkyDriveFolderId != null)
{
var task = GetRestoreStreamImpl();
task.Start();
return task.Result;
}
return Stream.Null;
}
private async Task<Stream> GetRestoreStreamImpl()
{
var getResult = await GetTaskAsync(SkyDriveFolderId + "/files");
List<object> data = (List<object>)getResult["data"];
foreach (IDictionary<string, object> dictionary in data)
{
if (dictionary.ContainsKey("name") && (string)dictionary["name"] == BackupFileName)
{
if (dictionary.ContainsKey("id"))
{
SkyDriveFileId = (string)dictionary["id"];
break;
}
}
}
if (String.IsNullOrEmpty(SkyDriveFileId))
{
MessageBox.Show("Restore failed: could not find backup file", "Backup", MessageBoxButton.OK);
return Stream.Null;
}
return await DownloadTaskAsync(SkyDriveFileId + "/content");
}
private Task<IDictionary<string,object>> GetTaskAsync(string path)
{
var client = new LiveConnectClient(_session);
var tcs = new TaskCompletionSource<IDictionary<string, object>>();
client.GetCompleted += (o, e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else if (e.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(e.Result);
};
client.GetAsync(path);
return tcs.Task;
}
private Task<Stream> DownloadTaskAsync(string path)
{
var client = new LiveConnectClient(_session);
var tcs = new TaskCompletionSource<Stream>();
client.DownloadCompleted += (o, e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else if (e.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(e.Result);
};
client.DownloadAsync(path);
return tcs.Task;
}
(wenn es in der Tat durch die Zeit, die await genannt wird abgeschlossen ist) es scheint, dass Microsoft bereits ein 'async' /' erwarten' Beispiel für das Live Connect SDK und dass mein Google-fu etwas Arbeit braucht. Das Beispiel befindet sich unter https://github.com/liveservices/LiveSDK/tree/master/Samples/WindowsPhone/LiveSDKAsyncAwaitSample und funktioniert etwas anders als das, was ich versuchte. –