跨线程同步/原子检查? [英] Synchronization across threads / atomic checks?

查看:80
本文介绍了跨线程同步/原子检查?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个方法调用程序,任何线程(例如,线程B)都可以调用该方法调用程序,该方法调用程序将在执行的主执行线程(Thead A)上的特定给定时间执行.

I need to create an method invoker that any thread (Thread B for example sake) can call, which will execute on the main executing thread (Thead A) at a specific given point in its execution.

示例用法如下:

static Invoker Invoker = new Invoker();

static void ThreadA()
{
    new Thread(ThreadB).Start();

    Thread.Sleep(...); // Hypothetic Alpha

    Invoker.Invoke(delegate { Console.WriteLine("Action"); }, true);

    Console.WriteLine("Done");

    Console.ReadLine();
}

static void ThreadB()
{
    Thread.Sleep(...); // Hypothetic Beta

    Invoker.Execute();
}

Invoker类如下:

The Invoker class looks like this:

public class Invoker
{
    private Queue<Action> Actions { get; set; }

    public Invoker()
    {
        this.Actions = new Queue<Action>();
    }

    public void Execute()
    {
        while (this.Actions.Count > 0)
        {
            this.Actions.Dequeue()();
        }
    }

    public void Invoke(Action action, bool block = true)
    {
        ManualResetEvent done = new ManualResetEvent(!block);

        this.Actions.Enqueue(delegate
        {
            action();
            if (block) done.Set();
        });

        if (block)
        {
            done.WaitOne();
        }
    }
}

在大多数情况下,此方法都可以正常工作,尽管如果出于某种原因(在WaitOne之前)执行了执行(因此,Set)也无法执行,在这种情况下,它将冻结(它允许线程继续执行,然后阻止).如果Alpha >> Beta,则可以复制.

This works fine in most cases, although it won't if, for any reason, the execution (and therefore the Set) is done before the WaitOne, in which case it will just freeze (it allows for the thread to proceed, then blocks). That could be reproduced if Alpha >> Beta.

我可以使用布尔值之类的东西,但是我在这里从未获得真正的原子安全性.我尝试了一些修复程序,但是在Beta >> Alpha的情况下,它们将无法正常工作.

I can use booleans and whatnot, but I'm never getting a real atomic safety here. I tried some fixes, but they wouldn't work in the case where Beta >> Alpha.

我还想到了同时锁定Invoker.Execute和Invoker.Invoke方法,以便确保在入队和等待之间不会发生执行.但是,问题在于该锁定还吞并了WaitOne,因此永远不会完成(死锁).

I also thought of locking around both the Invoker.Execute and Invoker.Invoke methods so that we are guaranteed that the execution does not occur between enqueing and waiting. However, the problem is that the lock also englobes the WaitOne, and therefore never finishes (deadlock).

在这种范例中,我应该如何获得绝对的原子安全?

How should I go about getting absolute atomic safety in this paradigm?

注意:从外部依赖关系来看,这确实是我使用此设计的要求.因此,更改设计不是一个现实的选择.

Note: It really is a requirement that I work with this design, from external dependencies. So changing design is not a real option.

编辑:我确实没有提及我想要一种阻塞行为(基于bool block),直到在调用Invoke上执行委托之前.

EDIT: I did forget to mention that I want a blocking behaviour (based on bool block) until the delegate is executed on the Invoke call.

推荐答案

使用Semaphore(Slim)代替ManualResetEvent.

创建一个最大计数为1的信号量,在调用线程中调用WaitOne(),然后在委托中调用Release().

Create a semaphore with an maximum count of 1, call WaitOne() in the calling thread, and call Release() in the delegate.

如果您已经呼叫Release(),则WaitOne()应该立即返回.

If you've already called Release(), WaitOne() should return immediately.

请确保在完成操作后将其保存为Dispose(),最好在using块中.
如果block为false,则不应该首先创建它(尽管对于SemaphoreSlim来说,还不错).

Make sure to Dispose() it when you're done, preferably in a using block.
If block is false, you shouldn't create it in the first place (although for SemaphoreSlim, that's not so bad).

这篇关于跨线程同步/原子检查?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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