C# 多线程:如何检查静态类是否繁忙
我有一个静态类,它有一个执行http请求的静态函数IsDataCorrect() 这个函数可以同时从多个线程调用,我想让第一个线程执行请求,其他线程应该被拒绝(这意味着它们的返回值应该为false,而不仅仅是被阻塞!),直到第一个线程完成请求后的半秒 之后,下一个获胜线程应该能够执行下一个请求,其他线程应该被拒绝,依此类推 这是我的方法,请有人确认这是否合理:C# 多线程:如何检查静态类是否繁忙,c#,multithreading,locking,C#,Multithreading,Locking,我有一个静态类,它有一个执行http请求的静态函数IsDataCorrect() 这个函数可以同时从多个线程调用,我想让第一个线程执行请求,其他线程应该被拒绝(这意味着它们的返回值应该为false,而不仅仅是被阻塞!),直到第一个线程完成请求后的半秒 之后,下一个获胜线程应该能够执行下一个请求,其他线程应该被拒绝,依此类推 这是我的方法,请有人确认这是否合理: static class MyClass { private static bool IsBusy = false;
static class MyClass
{
private static bool IsBusy = false;
private static object lockObject = new object();
public static bool IsDataCorrect(string testString)
{
lock (lockObject)
{
if (IsBusy) return false;
IsBusy = true;
}
var uri = $"https://something.com";
bool htmlCheck = GetDocFromUri(uri, 2);
var t = new Thread(WaitBeforeFree);
t.Start();
//Fast Evaluations
//...
return htmlCheck;
}
private static void WaitBeforeFree()
{
Thread.Sleep(500);
IsBusy = false;
}
}
访问函数的线程仍将在access for check
IsBusy
标志中序列化,因为由于在lockObject
上进行同步,一次只能有一个线程能够检查它。相反,您可以简单地尝试获取一个锁,因此,您不需要标志,因为锁本身将用作锁。其次,我每次都会替换启动新线程,只是为了休眠和重置标志,并用检查DateTime
字段来替换它
static class MyClass
{
private static DateTime NextEntry = DateTime.Now;
private static ReaderWriterLockSlim timeLock = new ReaderWriterLockSlim();
private static object lockObject = new object();
public static bool IsDataCorrect(string testString)
{
bool tryEnterSuccess = false;
try
{
try
{
timeLock.EnterReadLock()
if (DateTime.Now < NextEntry) return false;
}
finally
{
timeLock.ExitReadLock()
}
Monitor.TryEnter(lockObject, ref tryEnterSuccess);
if (!tryEnterSuccess) return false;
var uri = $"https://something.com";
bool htmlCheck = GetDocFromUri(uri, 2);
//Fast Evaluations
//...
try
{
timeLock.EnterWriteLock()
NextEntry = DateTime.Now.AddMilliseconds(500);
} finally {
timeLock.ExitWriteLock()
}
return htmlCheck;
} finally {
if (tryEnterSuccess) Monitor.Exit(lockObject);
}
}
}
静态类MyClass
{
private static DateTime NextEntry=DateTime.Now;
私有静态ReaderWriterLockSlim timeLock=新的ReaderWriterLockSlim();
私有静态对象lockObject=新对象();
公共静态bool IsDataCorrect(string testString)
{
bool-tryentersecsuccess=false;
尝试
{
尝试
{
timeLock.entereadlock()
如果(DateTime.Now
这种不启动新线程的方式更有效,DateTime访问是安全的,而且是并发的,所以线程只有在绝对必要时才会停止。否则,一切都会以最小的资源使用率继续运行。访问函数的线程仍然会在access for check
IsBusy
标志中序列化,因为由于在lockObject
上进行同步,一次只能有一个线程能够检查它。相反,您可以简单地尝试获取一个锁,因此,您不需要标志,因为锁本身将用作锁。其次,我每次都会替换启动新线程,只是为了休眠和重置标志,并用检查DateTime
字段来替换它
static class MyClass
{
private static DateTime NextEntry = DateTime.Now;
private static ReaderWriterLockSlim timeLock = new ReaderWriterLockSlim();
private static object lockObject = new object();
public static bool IsDataCorrect(string testString)
{
bool tryEnterSuccess = false;
try
{
try
{
timeLock.EnterReadLock()
if (DateTime.Now < NextEntry) return false;
}
finally
{
timeLock.ExitReadLock()
}
Monitor.TryEnter(lockObject, ref tryEnterSuccess);
if (!tryEnterSuccess) return false;
var uri = $"https://something.com";
bool htmlCheck = GetDocFromUri(uri, 2);
//Fast Evaluations
//...
try
{
timeLock.EnterWriteLock()
NextEntry = DateTime.Now.AddMilliseconds(500);
} finally {
timeLock.ExitWriteLock()
}
return htmlCheck;
} finally {
if (tryEnterSuccess) Monitor.Exit(lockObject);
}
}
}
静态类MyClass
{
private static DateTime NextEntry=DateTime.Now;
私有静态ReaderWriterLockSlim timeLock=新的ReaderWriterLockSlim();
私有静态对象lockObject=新对象();
公共静态bool IsDataCorrect(string testString)
{
bool-tryentersecsuccess=false;
尝试
{
尝试
{
timeLock.entereadlock()
如果(DateTime.Now
这种不启动新线程的方式更有效,DateTime访问是安全的,而且是并发的,所以线程只有在绝对必要时才会停止。否则,一切都会以最小的资源使用率继续进行。我看到你们正确地解决了这个问题,但我认为仍然有空间使它同时正确、高效和简单:)。 这样怎么样 编辑:编辑以使平静更容易,并成为示例的一部分
public static class ConcurrentCoordinationExtension
{
private static int _executing = 0;
public static bool TryExecuteSequentially(this Action actionToExecute)
{
// compate _executing with zero, if zero, set 1,
// return original value as result,
// successfull entry then result is zero, non zero returned, then somebody is executing
if (Interlocked.CompareExchange(ref _executing, 1, 0) != 0) return false;
try
{
actionToExecute.Invoke();
return true;
}
finally
{
Interlocked.Exchange(ref _executing, 0);//
}
}
public static bool TryExecuteSequentially(this Func<bool> actionToExecute)
{
// compate _executing with zero, if zero, set 1,
// return original value as result,
// successfull entry then result is zero, non zero returned, then somebody is executing
if (Interlocked.CompareExchange(ref _executing, 1, 0) != 0) return false;
try
{
return actionToExecute.Invoke();
}
finally
{
Interlocked.Exchange(ref _executing, 0);//
}
}
}
class Program
{
static void Main(string[] args)
{
DateTime last = DateTime.MinValue;
Func<bool> operation= () =>
{
//calming condition was not meant
if (DateTime.UtcNow - last < TimeSpan.FromMilliseconds(500)) return false;
last = DateTime.UtcNow;
//some stuff you want to process sequentially
return true;
};
operation.TryExecuteSequentially();
}
}
公共静态类ConcurrentCoordinationExtension
{
私有静态int_=0;
公共静态布尔操作依次执行(此操作操作执行)
{
//compat_执行时为零,如果为零,则设置为1,
//返回原始值作为结果,
//成功输入然后结果为零,返回非零,然后有人正在执行
if(interlocated.compareeexchange(ref _executing,1,0)!=0)返回false;
尝试
{
actionToExecute.Invoke();
返回true;
}
最后
{
联锁交换(参考执行,0)//
}
}
公共静态布尔函数依次执行(此函数操作执行)
{
//compat_执行时为零,如果为零,则设置为1,
//返回原始值作为结果,
//成功输入然后结果为零,返回非零,然后有人正在执行
if(interlocated.compareeexchange(ref _executing,1,0)!=0)返回false;
尝试
{
return actionToExecute.Invoke();
}
最后
{
联锁交换(参考执行,0)//
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{