C# 强制单线程访问资源

C# 强制单线程访问资源,c#,thread-safety,dispatcher,C#,Thread Safety,Dispatcher,目前,我在一个项目中有多个资源,只能从单个线程访问。一个例子是ZeroMQ服务器,另一个例子是三菱PLC通信模块,它不是线程安全的 现在我为任何需要单线程访问的资源创建一个单独的线程。我没有将其包装在类或任何东西中,因此我有一个ThreadStart(void)方法,每个类中都有一些属性,需要协调访问资源。然后,我使用一个与Invoke/BeginInvoke相结合的调度程序,强制仅从单独的线程进行访问 是否已有一些类可以协调从单个线程访问资源? 下面是一些示例代码,可以立即为我提供一个调度器:

目前,我在一个项目中有多个资源,只能从单个线程访问。一个例子是ZeroMQ服务器,另一个例子是三菱PLC通信模块,它不是线程安全的

现在我为任何需要单线程访问的资源创建一个单独的线程。我没有将其包装在类或任何东西中,因此我有一个
ThreadStart
(void)方法,每个类中都有一些属性,需要协调访问资源。然后,我使用一个与
Invoke
/
BeginInvoke
相结合的调度程序,强制仅从单独的线程进行访问

是否已有一些类可以协调从单个线程访问资源?

下面是一些示例代码,可以立即为我提供一个调度器:

object theLock = new object();
Dispatcher dispatcher = null;

lock (theLock)
{
    new Thread(new ThreadStart(() =>
    {
        lock (theLock)
        {
            dispatcher = Dispatcher.CurrentDispatcher;
            Monitor.Pulse(theLock);
        }
        Dispatcher.Run();
    })).Start();

    Monitor.Wait(theLock);
}

dispatcher.Invoke(...);
我可以将此代码封装在一个类中,以便在需要时创建线程和调度程序,但我无法想象这是协调对线程不安全资源的访问的最佳解决方案。

您是否尝试使用和?您可以在需要访问资源的任务中排队,然后启动一个任务,一个接一个地排队并运行该任务,这样就没有竞争条件了

static BlockingCollection<Action<StringBuilder>> queue = new BlockingCollection<Action<StringBuilder>>();

//Your thread unsafe resource...
static StringBuilder resource = new StringBuilder();

static void Main(string[] args)
{
    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            var action = queue.Take();
            action(resource);
        }
    });

    //Now to do some work you simply add something to the queue...
    queue.Add((sb) => sb.Append("Hello"));
    queue.Add((sb) => sb.Append(" World"));

    queue.Add((sb) => Console.WriteLine("Content: {0}", sb.ToString()));

    Console.ReadLine();
}
static BlockingCollection queue=new BlockingCollection();
//你的线程资源不安全。。。
静态StringBuilder资源=新建StringBuilder();
静态void Main(字符串[]参数)
{
Task.Factory.StartNew(()=>
{
while(true)
{
var action=queue.Take();
行动(资源);
}
});
//现在要做一些工作,只需向队列中添加一些内容。。。
queue.Add((sb)=>sb.Append(“Hello”);
queue.Add((sb)=>sb.Append(“世界”);
Add((sb)=>Console.WriteLine(“内容:{0}”,sb.ToString());
Console.ReadLine();
}

这一切都是静态的,有点难看,当然需要返工,但它应该是好的。其思想是将要执行的lambda排队,它们将一个接一个地执行,这样就不必在资源上同步。

用粗体字表示,我是否应该将问题放在底部附近?这会迫使它们(任务始终在同一线程上执行?它会降低复杂性吗?一个简短的例子会说一千多个单词…好吧,我当时没有答对问题。。。您想确保执行所有操作的线程始终是同一个线程吗?在这种情况下,我想会的,因为只有一个任务在运行。但是,我将如何处理队列,以及什么会迫使队列处理保持在同一个线程中?在我看来,我仍然需要创建一个单独的线程来完成这项工作,然后我将拥有某种队列,而不是
调度程序。另外,如果队列用完了怎么办?我需要显示器吗?我忽略了队列处理部分,但我认为它仍然忽略了通过单个线程协调对资源的访问的问题。它是一个阻塞队列,因此当其中没有任何内容时,处理将暂停,直到有内容为止。一旦有东西在里面,这个动作就会被执行,并将资源作为一个参数,所以只有那个动作在那个时候才能访问资源。两年后,我发现你是对的!但是,您的代码有一个问题,那就是使用
任务
构造的长时间运行的线程。使用
TaskCompletionSource
对一些容器进行排队很容易,以便使用
Task
s实现异步模式,然后在使用者线程中对其进行处理。