是否确定从多个线程等待同一个任务 - 在等待线程安全的? [英] Is it ok to await the same task from multiple threads - is await thread safe?

查看:133
本文介绍了是否确定从多个线程等待同一个任务 - 在等待线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

时的等待线程安全的?这似乎Task类是线程安全的,所以我想等待它也是线程安全的,但我还没有找到一个确认的任何地方。也就是线程安全定制awaiter一个要求 - 我的意思的IsCompleted,GetAwaiter等方法呢?即如果这些方法不是线程安全的,将等待是线程安全的?不过,我不认为需要自定义awaiter很快。

用户场景的一个例子:比方说,我有一个背景的任务,异步返回一个结果,然后从多个线程使用的:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Threading.Tasks;命名空间scratch1
{
    Foo类
    {
        任务< INT> _任务;        公共美孚()
        {
            _Task = Task.Run(异步()=> {等待Task.Delay(5000);返回5;});
        }        //从多个线程调用
        公共异步任务< INT>酒吧(int i)以
        {
            返回(的await _Task)+ I;
        }
    }    类节目
    {
        公共静态无效的主要(字串[] args)
        {
            富富=新的Foo();            清单<任务>任务=新的List<任务>();
            的foreach(在Enumerable.Range变种I(0,100))
            {
                tasks.Add(Task.Run(异步()=> {Console.WriteLine(的await foo.Bar(I));}));
            }            Task.WaitAll(tasks.ToArray());
        }
    }
}


解决方案

至于你提到的,等待够薄,它没有看到线程摆在首位

相关联的code等待(编译器生成的$ C $状态机内C,并在BCL的支持类)将只运行上一次一个线程。 (从awaitable回来时,它可以切换到不同的线程,但previous运行将已经完成)

实际的线程安全取决于你正在等待的对象。结果
它必须有一个线程安全的方式来增加回调(或等待 ING两次一次可能会断裂)。

在此外,它必须调用回调恰好一次,或者它可以打破状态机。 (特别是如果它运行其上在同一时间两个线程的回调,事情会严重错误)

任务是线程安全的。

Is await thread safe? It seems the Task class is thread safe so I guess awaiting it is also thread safe but I haven't found a confirmation anywhere. Also is thread safety a requirement for custom awaiter - I mean for the IsCompleted, GetAwaiter, etc. methods? I.e. if those methods are not thread safe, will await be thread safe? However, I don't expect needing a custom awaiter anytime soon.

An example of user scenario: Let's say I have a background task which returns a result asynchronously, which is then used from multiple threads:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace scratch1
{
    class Foo
    {
        Task<int> _task;

        public Foo()
        {
            _task = Task.Run(async () => { await Task.Delay(5000); return 5; });
        }

        // Called from multiple threads
        public async Task<int> Bar(int i)
        {
            return (await _task) + i;
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            Foo foo = new Foo();

            List<Task> tasks = new List<Task>();
            foreach (var i in Enumerable.Range(0, 100))
            {
                tasks.Add(Task.Run(async () => { Console.WriteLine(await foo.Bar(i)); })); 
            }

            Task.WaitAll(tasks.ToArray());
        }
    }
}

解决方案

As you alluded to, await is thin enough that it doesn't see threads in the first place.

The code associated with await (the compiler-generated code within the state machine, and the support classes in the BCL) will only ever run on one thread at a time. (it can switch to a different thread when coming back from the awaitable, but the previous run will have already finished)

The actual thread-safety depends on the object you're awaiting.
It must have a thread-safe way to add callbacks (or awaiting it twice at once may break).

In addition, it must call the callback exactly once, or it may break the state machine. (in particular, if it runs its callback on two threads at the same time, things will go horribly wrong)

Task is thread-safe.

这篇关于是否确定从多个线程等待同一个任务 - 在等待线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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