Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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# 为什么我的代码没有';同步时不能正常工作?_C#_Multithreading_Thread Safety_Mutex - Fatal编程技术网

C# 为什么我的代码没有';同步时不能正常工作?

C# 为什么我的代码没有';同步时不能正常工作?,c#,multithreading,thread-safety,mutex,C#,Multithreading,Thread Safety,Mutex,我使用这个类来防止两个应用程序(一个windows应用程序和一个运行在同一操作系统上的web应用程序)同时使用共享文件。但是我得到一个错误:“对象同步方法是从一个未同步的代码块调用的。” 这两个项目中都存在此类 注意:我不是在寻找问题的解决方案来访问文件,我需要知道为什么我的代码有问题。因为我还想将此代码用于其他目的。 谢谢。我认为这可能是由种族状况引起的(正如/u/Sinatr在对问题的评论中所建议的) 以下代码复制了该问题: using System; using System.Thread

我使用这个类来防止两个应用程序(一个windows应用程序和一个运行在同一操作系统上的web应用程序)同时使用共享文件。但是我得到一个错误:“对象同步方法是从一个未同步的代码块调用的。”

这两个项目中都存在此类

注意:我不是在寻找问题的解决方案来访问文件,我需要知道为什么我的代码有问题。因为我还想将此代码用于其他目的。
谢谢。

我认为这可能是由种族状况引起的(正如/u/Sinatr在对问题的评论中所建议的)

以下代码复制了该问题:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            var t1 = Task.Run(func1);
            var t2 = Task.Run(func2);

            Task.WaitAll(t1, t2);

            Console.WriteLine("Done. Press <ENTER>");
            Console.ReadLine();
        }

        static void func1()
        {
            using (new SharedMutex("test"))
            {
                Thread.Sleep(2000);
            }
        }

        static void func2()
        {
            using (new SharedMutex("test"))
            {
                Thread.Sleep(1000);
            }
        }
    }

    class SharedMutex : IDisposable
    {
        readonly Mutex mutex;

        public SharedMutex(string name)
        {
            bool m = Mutex.TryOpenExisting(name, out mutex);

            if (m)
            {
                mutex.WaitOne();
            }
            else
            {
                Thread.Sleep(10); // Simulate a short delay.
                mutex = new Mutex(true, name);
            }
        }

        public void Dispose()
        {
            mutex.ReleaseMutex();
            mutex.Dispose();
        }
    }
}
你不在乎它是不是新创建的。互斥体构造函数会为您解决这个问题

即使这不是问题所在,我仍然认为您应该使用上面的实现,因为它没有潜在的竞争条件

如各国所述:

如果name不为null且initiallyOwned为true,则调用线程 仅当作为结果创建了命名的系统互斥体时,才拥有互斥体 这个电话的电话号码。因为没有机制来确定 已创建命名系统互斥体,最好为 调用此构造函数重载时initiallyOwned


您的“访问共享文件”是否包含一个
wait
?“互斥体具有线程亲缘关系,互斥体的所有者是线程。获取该互斥体的线程也必须是调用ReleaseMutex()的线程。这就是代码爆炸的原因。”-此错误表示您正试图从另一个线程释放互斥体,而不是从拥有所有权的线程释放互斥体。如果没有,则很难添加更多内容。@Sinatr是否应该重新打开它?我认为问题在于
TryOpenExisting
返回
false
和试图在
else
中创建具有所有权的互斥体之间的竞争条件。你可能不会成功。您没有按照一式两份的答复来处理这个案件。谢谢。我不知道程序可能不会在新的互斥锁上等待其他线程(true,name);我也不知道比赛条件到底意味着什么。你能解释一下或者发送一个链接吗?@DadkhahDadkhah有,但基本上这意味着你有一些代码,当两个线程几乎同时调用它时,可能会出错。
using (new SharedMutex(SharedMutex.Logs))
                {
                   ///access the shared file
                }
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            var t1 = Task.Run(func1);
            var t2 = Task.Run(func2);

            Task.WaitAll(t1, t2);

            Console.WriteLine("Done. Press <ENTER>");
            Console.ReadLine();
        }

        static void func1()
        {
            using (new SharedMutex("test"))
            {
                Thread.Sleep(2000);
            }
        }

        static void func2()
        {
            using (new SharedMutex("test"))
            {
                Thread.Sleep(1000);
            }
        }
    }

    class SharedMutex : IDisposable
    {
        readonly Mutex mutex;

        public SharedMutex(string name)
        {
            bool m = Mutex.TryOpenExisting(name, out mutex);

            if (m)
            {
                mutex.WaitOne();
            }
            else
            {
                Thread.Sleep(10); // Simulate a short delay.
                mutex = new Mutex(true, name);
            }
        }

        public void Dispose()
        {
            mutex.ReleaseMutex();
            mutex.Dispose();
        }
    }
}
class SharedMutex : IDisposable
{
    readonly Mutex mutex;

    public SharedMutex(string name)
    {
        mutex = new Mutex(false, name);
        mutex.WaitOne();
    }

    public void Dispose()
    {
        mutex.ReleaseMutex();
        mutex.Dispose();
    }
}