C# async 与 await 疑问

WangxiaoluWang 2016-08-11 11:34:59

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,但是调试时发现代码都是执行完下载代码后才往后执行的,初次使用望指教。
...全文
245 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
烟波钓 2016-08-12
  • 打赏
  • 举报
回复
假设一种情景,你做的一个桌面端程序,有一个按钮,点击这个按钮后去上传一个文件(文件很大要很久),为不让用户等待 只能后台下,上传完文件得到的路径还需要保存的数据库里面,同时还需要记录日志。 整体来说三件事 1.后台下载文件,下载完后有后续处理流程------起来一个线程跑,跑完需要有回调把得到的文件地址存到数据库中,但也与主线程(UI)无关 2.记录日志,纯操作日志,成功与否与业务流程无关------这个直接起来一个线程去跑,跑完就跑完了 没有回调并且与主线程无关 3.界面正常响应

void 按钮点击事件响应方法()
{
用线程池起来一个线程记录日志;//不阻塞 无回调
上传文件并处理方法();//不阻塞  看似没有回调,其实回调放到了这个方法里面
}

async void  上传文件并处理方法() //此处async理解为这是一个与主线程无关的处理流程
{
string newURL=await  上传文件方法();
数据库保存新文件地址方法();//这个理解为上传文件方法执行完后,根据他的返回值执行的回调
}
Task<string> 上传文件方法()
{
 return Task.Run(() =>
            {
            // 具体的上传文件逻辑
             return 上传文件后得到的新地址;
            });
}
john_QQ:2335298917 2016-08-11
  • 打赏
  • 举报
回复
调用async方法时,await关键字会自动暂停当前线程中任何其他活动,直到任务完成,离开调用线程,这是精通C#(第6版)上的原话,网上有这本书,你可以下载下来看一下http://www.jb51.net/books/327829.html
  • 打赏
  • 举报
回复
如果你根本不需要回调,那么不要写 await。 如果你根本不需要回调,却使用了 async/await 模式,那么就完全没有理解这个是干什么的了。
  • 打赏
  • 举报
回复
引用 楼主 WangxiaoluWang 的回复:
如上代码,加了async和await,但是调试时发现代码都是执行完下载代码后才往后执行的,初次使用望指教。
异步出现在调用 GetBody 的地方(你根本没有贴出来的部分),而不是在它内部。在 GetBody 内部,是异步回调的,在还没有执行完 foreach 的时候,GetBody 的调用者的后续代码就提前执行了。那才是你应该贴出来、应该调试的。 async/await 实际上是障眼法,让人混乱。如果你没有普通的多线程异步回调的知识和丰富的测试调试经验,那么 async/await 实际上很容易误导你的思路。用一个“看似顺序的程序代码”来实现异步多线程编程,这要求一个人有更高的抽象编程能力,而并不像微软某些讲师吹嘘de那样是“降低技术要求”的。虽然代码简单了,但是调试和测试更难了。
Forty2 2016-08-11
  • 打赏
  • 举报
回复
await的中文翻译为:等待 你加了等待,当然要先下载完,才会运行后续的指令。 await System.Threading.Tasks.Task.Run(() => { DownLoadFile... // 后续指令...
  • 打赏
  • 举报
回复
去掉await再试一次
  • 打赏
  • 举报
回复
这得先理解异步和异步编程的概念,如果你用过Net4.0之前异步编程,那么理解起来要容易很多 正如LS所说,这两个东西只是编译器使了障眼法,生成了额外的代码段来进行同步
WangxiaoluWang 2016-08-11
  • 打赏
  • 举报
回复
async/await 有啥用呢?谁能给举个项目上的栗子?现在代码改成这样了:

 public 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);//保存的文档路径
                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;
    }

private void DownLoadFile(string path, EmailMessage email, Attachment at)
    {
        System.Threading.Tasks.Task.Run(() =>
        {
            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)
            {

            }
        });
    }

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧