你在那里,异步写入值? [英] Are you there, asynchronously written value?

查看:19
本文介绍了你在那里,异步写入值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近几天我一直在阅读有关 async/await 的文章.昨天我发现

如果从非 UI 上下文调用,则无法保证延续将在同一线程中运行.通常它会在 ThreadPool 线程中运行.鉴于读取的字段不是易失性的,如果没有插入必要的障碍,您可能会获得以前的值.但您无需担心,因为TPL 已经为您做了这些.

来自上面的链接

<块引用>

是的,TPL 在任务排队时包含适当的障碍,并且在任务执行的开始/结束时,值是适当地使可见

因此,使用 TPL,鉴于任务已经完成,您无需担心内存障碍.但是,如果您手动创建线程(您不应该这样做)并直接处理线程——您将不得不插入必要的内存屏障.

顺便说一句,ReadToEnd 是一个阻塞调用.我不会在 UI 线程中调用它.我会使用 ReadToEndAsync 代替让您的 UI 线程自由.我不会在这里使用字段;我将从异步方法返回值,因为每个方法调用都依赖于参数,因此从方法返回值是有意义的.

所以,你的方法会变成下面这样

private async TaskSendDataAsync(字符串网址){var request = WebRequest.Create(url);using(var response = await request.GetResponseAsync());using(var reader = new StreamReader(request.GetResponseStream());返回等待 reader.ReadToEndAsync();}

The last couple of days I've been reading about async/await. Yesterday I found this video on Channel 9 what made wonder about some things. Please consider the slide below.

Aside from the issues Lucian Wischik addresses, I wondered about variable assignment. Say we changed the async void into async Task, and added await before the SendData call. This enables us to get the stream, assign the variable m_GetResponse, wait for two seconds and print it. But what happens to the variable? It could be written by a different thread than it is read. Do we need some sort of a memory barrier here, make the variable volatile, or perhaps something else? Could it still be null when we print it?

解决方案

In the above example, it is safe to read the m_GetResponse because assignment will happen in same UI thread given that this is being called from UI.

This is because SynchronizationContext will be captured and continued when the async method resumes. So it is the same UI thread which writes the field and reading it. This isn't a problem here. Refer my related answer here

If called from non UI context, there is no guarantee that continuations will be ran in same thread. Usually it will be ran in ThreadPool thread. Given that the field read isn't volatile it is possible that you could get the previous value if necessary barriers are not inserted. But you don't need to worry about it because TPL already does this for you.

From the above link

Yes, TPL includes the appropriate barriers when tasks are queued and at the beginning/end of task execution so that values are appropriately made visible

So with TPL, you don't need to worry about memory barriers given that the Tasks are already completed. But if you're creating threads manually(which you shouldn't be doing) and dealing with threads directly --you'll have to insert necessary memory barriers.

Btw, ReadToEnd is a blocking call. I would not call it in UI thread. I'd use ReadToEndAsync instead to make your UI thread free. And I'll not use field here; I'll return the value from async method because every method call is just dependent on the parameter so it makes sense to return the value from the method.

So, your method will become something like the following

private async Task<string> SendDataAsync(string url)
{
    var request = WebRequest.Create(url);
    using(var response = await request.GetResponseAsync());
    using(var reader = new StreamReader(request.GetResponseStream());
        return await reader.ReadToEndAsync();
}

这篇关于你在那里,异步写入值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆