.NET 3.5 C#没有提供锁定所需的功能:再次计数异步保存,直到0
我有一些记录,我想异步保存到数据库。我把它们分批组织起来,然后发送出去。随着时间的推移,批次将被处理 同时,用户还可以继续工作。当任何保存批处理仍在异步运行时,有一些关键操作我想将其锁定 保存是使用TableServiceContext和方法.BeginSave()完成的,但我认为这应该是无关的 我想做的是,每当异步保存启动时,增加锁计数,当它完成时,减少锁计数,以便在所有操作完成后立即为零。我想锁定关键操作,只要计数不为零。此外,我想通过业务对象来限定锁,例如.NET 3.5 C#没有提供锁定所需的功能:再次计数异步保存,直到0,c#,.net,locking,semaphore,C#,.net,Locking,Semaphore,我有一些记录,我想异步保存到数据库。我把它们分批组织起来,然后发送出去。随着时间的推移,批次将被处理 同时,用户还可以继续工作。当任何保存批处理仍在异步运行时,有一些关键操作我想将其锁定 保存是使用TableServiceContext和方法.BeginSave()完成的,但我认为这应该是无关的 我想做的是,每当异步保存启动时,增加锁计数,当它完成时,减少锁计数,以便在所有操作完成后立即为零。我想锁定关键操作,只要计数不为零。此外,我想通过业务对象来限定锁,例如 我没有找到一个.NET3.5C#
我没有找到一个.NET3.5C#锁定方法,它确实满足了这个要求。如果计数为0,则信号量不包含要检查的方法。否则,具有无限最大计数的信号量就可以了 如果唯一的逻辑涉及值是否为非零,那么锁计数的目的是什么 如果要逐个类型执行此操作,可以采用以下方法:
public class BusinessObject1
{
private static readonly object lockObject = new object();
public static object SyncRoot { get { return lockObject; } }
}
(其他业务对象采用相同的模式)
如果随后将保存操作和关键操作放在一个块中,如下所示:
lock(BusinessObject1.SyncRoot)
{
// do work
}
lock(BusinessObject1.SyncRoot)
lock(BusinessObject2.SyncRoot)
lock(BusinessObject3.SyncRoot)
{
// do work
}
您将使保存和关键操作任务互斥
因为您希望它是细粒度的,所以可以像这样级联锁:
lock(BusinessObject1.SyncRoot)
{
// do work
}
lock(BusinessObject1.SyncRoot)
lock(BusinessObject2.SyncRoot)
lock(BusinessObject3.SyncRoot)
{
// do work
}
实际上,
Semaphare
确实有一个检查计数是否为零的方法。使用具有零超时的WaitOne方法。它将返回一个值,指示是否获取了信号量。如果它返回false,则它未被获取,这意味着它的计数为零
var s = new Semaphore(5, 5);
while (s.WaitOne(0))
{
Console.WriteLine("acquired");
}
Console.WriteLine("no more left to acquire");
我假设,当您说锁定用户时,在操作完成时,它不是字面上的“锁定”,因为这会阻止UI线程,并在遇到锁定时冻结应用程序。我假设您的意思是可以检查某些状态,以便禁用/启用UI控件 可以使用类似以下代码的无锁代码:
public class BusyState
{
private int isBusy;
public void SignalTaskStarted()
{
Interlocked.Increment(ref isBusy);
}
public void SignalTaskFinished()
{
if (Interlocked.Decrement(ref isBusy) < 0)
{
throw new InvalidOperationException("No tasks started.");
}
}
public bool IsBusy()
{
return Thread.VolatileRead(ref isBusy) > 0;
}
}
public class BusinessObject
{
private readonly BusyState busyState = new BusyState();
public void Save()
{
//Raise a "Started" event to disable UI controls...
//Start a few async tasks which call CallbackFromAsyncTask when finished.
//Start task 1
busyState.SignalTaskStarted();
//Start task 2
busyState.SignalTaskStarted();
//Start task 3
busyState.SignalTaskStarted();
}
private void CallbackFromAsyncTask()
{
busyState.SignalTaskFinished();
if (!busyState.IsBusy())
{
//Raise a "Completed" event to enable UI controls...
}
}
}
公共类总线状态
{
私家车很忙;
public void SignalTaskStarted()
{
联锁。增量(参考忙);
}
public void SignalTaskFinished()
{
if(联锁减量(参考忙)<0)
{
抛出新的InvalidOperationException(“未启动任务”);
}
}
公共图书馆很忙
{
返回线程volatireRead(ref isBusy)>0;
}
}
公共类BusinessObject
{
private readonly BusyState BusyState=new BusyState();
公共作废保存()
{
//引发“已启动”事件以禁用UI控件。。。
//启动一些异步任务,这些任务在完成时调用callbackromasynctask。
//启动任务1
busyState.SignalTaskStarted();
//开始任务2
busyState.SignalTaskStarted();
//开始任务3
busyState.SignalTaskStarted();
}
私有void callbackromasynctask()
{
busyState.SignalTaskFinished();
如果(!busyState.IsBusy())
{
//引发“已完成”事件以启用UI控件。。。
}
}
}
计数方面封装在BusyState中,然后在业务对象中使用它来通知任务开始和停止。可以挂接引发已启动和已完成事件,以实现启用和禁用UI控件,从而在异步操作完成时锁定用户
这里显然有很多关于处理错误条件等的警告,所以只需要一些基本的大纲代码