C# async 与 await 疑问

.Net技术 码拜 5年前 (2016-06-08) 557次浏览
 private void DownLoadFile(string path, EmailMessage email, Attachment at)
    {
        try
        {
            Attachment attachment = email.Attachments.Single(x => x.ContentId == at.ContentId);
            attachment.Load();
            FileAttachment fileAttachment = attachment as FileAttachment;
            fileAttachment.Load();
            byte[] bytes = fileAttachment.Content;
            File.WriteAllBytes(path, bytes);
        }
        catch (Exception ex)
        {
        }
    }
public async System.Threading.Tasks.Task<ExchangeEmail> GetBody(ItemId Id)
    {
        EmailMessage email = EmailMessage.Bind(service, Id);
        #region xiaolu Add 15-7-8 附件内容
        Dictionary<string, string> atts = new Dictionary<string, string>();
        if (email.HasAttachments)
        {
            var att = email.Attachments;
            foreach (var at in att)
            {
                var guid = Guid.NewGuid().ToString();
                var ext = at.Name.Substring(at.Name.LastIndexOf("."));
                var linpath = "http://" + HttpContext.Current.Request.Url.Host + ":" + HttpContext.Current.Request.Url.Port + "/UpLoad/App/Mail/" + guid + ext;//连接地址
                atts.Add(linpath, at.Name);
                var path = HttpContext.Current.Server.MapPath("~/UpLoad/App/Mail/" + guid + ext);//保存的文档路径
                await System.Threading.Tasks.Task.Run(() => { DownLoadFile(path, email, at); });
            }
        }
        #endregion
        ExchangeEmail mee = new ExchangeEmail();
        mee.Body = email.Body;
        mee.DateTimeCreated = email.DateTimeCreated;
        mee.DateTimeReceived = email.DateTimeReceived;
        mee.Id = email.Id;
        mee.Sender = email.Sender.Name;
        mee.Subject = email.Subject;
        mee.Atts = atts;
        mee.SenderEmail = email.Sender.Address;
        //mee.Body = email.TextBody;
        return mee;
    }

如上代码,加了async和await,但是调试时发现代码都是执行完下载代码后才往后执行的,初次使用望指点。

解决方案

10

去掉await再试一次

10

await的中文翻译为:等待
你加了等待,当然要先下载完,才会运行后续的指令。
await System.Threading.Tasks.Task.Run(() => { DownLoadFile…
// 后续指令…

10

引用:

如上代码,加了async和await,但是调试时发现代码都是执行完下载代码后才往后执行的,初次使用望指点。

异步出现在调用 GetBody 的地方(你根本没有贴出来的部分),而不是在它内部。在 GetBody 内部,是异步回调的,在还没有执行完 foreach 的时候,GetBody 的调用者的后续代码就提前执行了。那才是你应该贴出来、应该调试的。
async/await 实际上是障眼法,让人混乱。假如你没有普通的多线程异步回调的知识和丰富的测试调试经验,那么 async/await 实际上很容易误导你的思路。用一个“看似顺序的程序代码”来实现异步多线程编程,这要求一个人有更高的抽象编程能力,而并不像微软某些讲师吹嘘de那样是“降低技术要求”的。虽然代码简单了,但是调试和测试更难了。

10

调用async方法时,await关键字会自动暂停当前线程中任何其他活动,直到任务完成,离开调用线程,这是精通C#(第6版)上的原话,网上有这本书,你可以下载下来看一下http://www.jb51.net/books/327829.html

10

假设一种情景,你做的一个桌面端程序,有一个按钮,点击这个按钮后去上传一个文件(文件很大要很久),为不让用户等待 只能后台下,上传完文件得到的路径还需要保存的数据库里面,同时还需要记录日志。
整体来说三件事
1.后台下载文件,下载完后有后续处理流程–起来一个线程跑,跑完需要有回调把得到的文件地址存到数据库中,但也与主线程(UI)无关
2.记录日志,纯操作日志,成功与否与业务流程无关–这个直接起来一个线程去跑,跑完就跑完了  没有回调并且与主线程无关
3.界面正常响应

void 按钮点击事件响应方法()
{
用线程池起来一个线程记录日志;//不阻塞 无回调
上传文件并处理方法();//不阻塞  看似没有回调,其实回调放到了这个方法里面
}
async void  上传文件并处理方法() //此处async理解为这是一个与主线程无关的处理流程
{
string newURL=await  上传文件方法();
数据库保存新文件地址方法();//这个理解为上传文件方法执行完后,根据他的返回值执行的回调
}
Task<string> 上传文件方法()
{
 return Task.Run(() =>
            {
            // 具体的上传文件逻辑
             return 上传文件后得到的新地址;
            });
}

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C# async 与 await 疑问
喜欢 (0)
[1034331897@qq.com]
分享 (0)