Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#相当于Java ExecutorService.newSingleThreadExecutor(),或:如何序列化对资源的多线程访问_C#_.net_Multithreading_Concurrency - Fatal编程技术网

C#相当于Java ExecutorService.newSingleThreadExecutor(),或:如何序列化对资源的多线程访问

C#相当于Java ExecutorService.newSingleThreadExecutor(),或:如何序列化对资源的多线程访问,c#,.net,multithreading,concurrency,C#,.net,Multithreading,Concurrency,我的代码中有几种情况,不同的线程可以创建工作项,由于各种原因,这些工作项不应该并行完成。我想确保工作以先进先出的方式完成,不管它来自哪个线程。在Java中,我将工作项放在一个单线程的ExecutorService;C#中是否有等价物?我用队列和一堆lock(){}块拼凑了一些东西,但是如果能够使用现成的东西并进行测试,那就太好了 更新:是否有人拥有System.Threading.Tasks的经验?它有解决这类问题的办法吗?我正在写一个Monotouch应用程序,所以谁知道我是否能找到一个可以开

我的代码中有几种情况,不同的线程可以创建工作项,由于各种原因,这些工作项不应该并行完成。我想确保工作以先进先出的方式完成,不管它来自哪个线程。在Java中,我将工作项放在一个单线程的
ExecutorService
;C#中是否有等价物?我用
队列
和一堆
lock(){}
块拼凑了一些东西,但是如果能够使用现成的东西并进行测试,那就太好了

更新:是否有人拥有System.Threading.Tasks的经验?它有解决这类问题的办法吗?我正在写一个Monotouch应用程序,所以谁知道我是否能找到一个可以开始工作的后端口版本,但这至少是未来需要考虑的事情

更新#2对于不熟悉我所说的Java库的C#开发人员来说,基本上我想要的是一种让各个线程传递工作项的东西,这样所有这些工作项都将在一个线程(不是任何调用线程)上运行



更新,2018年6月:如果我现在正在设计一个类似的系统,我可能会使用。不过,我要留下公认的一个,因为如果你在Rx中思考,你可能甚至不会问这个问题,我认为
ConcurrentQueue
更容易进入预Rx程序。

不是本地的AFAIK,但看看这个:

我相信这可以通过使用。然而,我这样做只是为了回发到UI线程,它已经有了由.NET提供的同步上下文(如果被告知要安装的话)——不过我不知道如何准备从“普通线程”使用它

我为“custom synchronizationcontext provider”找到了一些链接(我没有时间查看这些链接,不完全了解工作/上下文,也没有任何其他信息):


  • 愉快的编码。

    正如我在评论中所写,您自己发现
    lock
    语句可以完成这项工作

    如果您有兴趣获得一个“容器”,它可以简化管理工作项队列的工作,请查看
    ThreadPool


    我认为,在一个设计良好的体系结构中,有了这两个元素(
    ThreadPool
    类和
    lock
    语句),您可以轻松成功地序列化对资源的访问。

    更新:解决关于浪费资源的评论(如果您没有使用Rx),您可以使用
    BlockingCollection
    (如果使用默认构造函数,它会包装一个
    ConcurrentQueue
    ),只需调用
    .getconsumineGenumerable()
    。如果工作是长时间运行的,则会有一个重载占用
    CancellationToken
    。请参见下面的示例


    您可以使用(如果monotouch支持.NET4?)它是线程安全的,我认为它的实现实际上是无锁的。如果您有一个长时间运行的任务(比如在windows服务中),那么这个方法非常有效

    通常,您的问题听起来像是有多个生产者和一个消费者

    var work = new BlockingCollection<Item>();
    var producer1 = Task.Factory.StartNew(() => {
        work.TryAdd(item); // or whatever your threads are doing
    });
    var producer2 = Task.Factory.StartNew(() => {
        work.TryAdd(item); // etc
    });
    var consumer = Task.Factory.StartNew(() => {
        foreach (var item in work.GetConsumingEnumerable()) {
            // do the work
        }
    });
    Task.WaitAll(producer1, producer2, consumer);
    
    var work=new BlockingCollection();
    var producer1=Task.Factory.StartNew(()=>{
    work.TryAdd(item);//或线程正在执行的任何操作
    });
    var producer2=Task.Factory.StartNew(()=>{
    work.TryAdd(项);//等
    });
    var consumer=Task.Factory.StartNew(()=>{
    foreach(work.GetConsumingEnumerable()中的变量项){
    //做这项工作
    }
    });
    Task.WaitAll(生产者1、生产者2、消费者);
    

    如果您有一个有限的工作项池,则应该使用。显示所有新的并发收集类型。

    现在有一个更现代的解决方案-类。

    如果工作应该以FIFO方式完成,为什么要创建“各种”线程?为什么不在单个线程上工作?@标记各种线程的存在还有其他原因——一些工作是由UI活动触发的,一些是由对网络请求的响应触发的,一些是由计时器触发的。对于这个问题:“如何序列化对资源的多线程访问?”您自己回答:在资源上使用lock()语句(或包含它们的物体)。我问题中的相关短语是“拼凑在一起”,而你答案中的相关短语是“在精心设计的建筑中”。事实上,虽然我不会残忍地否决它,“工具是存在的,去弄清楚如何建造它”这根本不是一个答案。你可以投票否决所有你想要的。我没有时间做一个完整的例子让你复制粘贴并完成你的工作。你写了关于队列的文章,我想你用它来管理线程,我建议你看看ThreadPool类来简化你的工作。怎么了?!是的,如果我在做那个项目的话现在我再次使用Rx架构。虽然此解决方案可能与Java解决方案具有相同的结果,
    使用者
    线程将继续运行。
    TryDequeue
    仅提供并发安全性,但如果队列中没有元素,它将不会继续等待。如果队列中没有元素,则有一个阅读正在运行的while循环。Java版本绝对不会像这样浪费资源。相比于此,
    wait
    -
    notify
    解决方案更可取。您可以使用BlockingCollection.CompleteAdding()方法,该方法将阻止foreach使用者线程进一步运行。