c# – 在Live SDK中使用async / await
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 在Live SDK中使用async / await,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4847字,纯文字阅读大概需要7分钟。
内容图文
![c# – 在Live SDK中使用async / await](/upload/InfoBanner/zyjiaocheng/784/4c41d6ee27954fd198f7b344cbced75c.jpg)
从我所看到的使用异步CTP和事件异步模式,我在这里的代码应该工作正常,var result1 = await tcs1.Task阻塞,直到clientGetFileList.GetCompleted触发.然而,最终发生的事情是我在返回GetRestoreStreamAree()时被反弹回GetRestoreStream.结果从未返回 – 相反,我的应用程序几乎锁定了我.
有人可以向我解释一下我做错了什么吗?
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
}
更新:这段代码似乎一路走来,但task.Start()抛出了InvalidOperationException,所以我从来没有真正得到过最后的流.将它包装在try / catch中也不会改变任何东西 – 如果没有try / catch,InvalidOperationException会被进一步向上捕获,而操作运行时会高兴地忽略它的结果永远不会被使用的事实;有了它,task.Result就像上面的代码一样冻结了东西.
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;
}
解决方法:
您误解了async / await的工作方式.基本上,您的代码在var result1及更低版本处阻塞.但是,await允许的是调用async方法的代码(在本例中为GetRestoreStream),只要调用在其前面等待的长时间运行的任务*,就会返回该代码.如果您不依赖.Result,那么您的GetRestoreStream方法将完成.但是,由于您需要结果,因此GetRestoreStream方法在等待GetRestoreStreamAwait完成时变为同步.我将很快添加一些视觉效果.
以下是一些示例代码流程:
-GetRestoreStream calls GetRestoreStreamAwait
---GetRestoreStreamAwait calls an async task
-GetRestoreStreamAwait returns to GetRestoreStream with a pending result
-GetRestoreStream can do anything it wants, but if it calls for the pending result, it will block
---GetRestoreStreamAwait finally finishes its async task and continues through its code, returning a result
-Any code in GetRestoreStream that was waiting for the result receives the Result
这不是最好的图形表示,希望它有助于解释它.需要注意的是,由于异步的性质,代码流不是您习惯使用的代码流
所以,我的猜测是你的应用程序只是因为你试图访问尚未提供的结果而锁定,所有你应该做的就是等待tcs1.Task完成.如果要避免锁定,则需要嵌套调用,以便GetRestoreStream也是异步方法.但是,如果结果是您最终要查找的结果,那么您将需要等待返回,或者只是设置一个像往常一样的异步模式的回调
*请注意,我说长时间运行的任务,因为编译器不会浪费时间重写已经完成的代码(如果它确实在调用await时完成)
更新…试试这个
protected override Stream GetRestoreStream()
{
if (SkyDriveFolderId != null)
return GetRestoreStreamAwait().Result;
return Stream.Null;
}
private async Task<Stream> GetRestoreStreamAwait()
{
try
{
LiveConnectClient clientGetFileList = new LiveConnectClient(_session);
TaskCompletionSource<LiveOperationCompletedEventArgs> tcs1 = new TaskCompletionSource<LiveOperationCompletedEventArgs>();
EventHandler<LiveOperationCompletedEventArgs> d1 =
(o, e) =>
{
try
{
tcs1.TrySetResult(e);
}
catch(Exception ex)
{
tcs1.TrySetResult(null);
}
};
clientGetFileList.GetCompleted += d1;
clientGetFileList.GetAsync(SkyDriveFolderId + "/files");
var result1 = await tcs1.Task;
clientGetFileList.GetCompleted -= d1;
// ... method continues for a while
}
catch(Exception ex)
{
return null;
}
}
内容总结
以上是互联网集市为您收集整理的c# – 在Live SDK中使用async / await全部内容,希望文章能够帮你解决c# – 在Live SDK中使用async / await所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。