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