在我们的Legacy项目中,我们使用以下代码进行异步操作:
public interface IAsyncOperation
{
OperationToken Token { get; }
bool IsCompleted { get; }
Exception Exception { get; }
bool Wait(int timeout);
}
/// <summary>
/// Asynchronous operation that may be executed on a separate thread.
/// IsCompleted and Exception would be synchronized after invoking Wait.
/// </summary>
public abstract class AsyncOperation : IAsyncOperation
{
protected readonly object CompletionLock = new object();
private volatile bool isCompleted; // volatile in order not to change the order of writing Exception and Result
protected AsyncOperation(bool isCompleted = false)
{
IsCompleted = isCompleted;
Token = OperationToken.New();
}
public OperationToken Token { get; protected set; }
public bool IsCompleted
{
get { return isCompleted; }
protected set { isCompleted = value; }
}
public Exception Exception { get; protected set; }
public bool Wait(int timeout)
{
if (!IsCompleted)
{
lock (CompletionLock)
{
if (!IsCompleted)
{
Monitor.Wait(CompletionLock, timeout);
}
}
}
return IsCompleted;
}
protected void Complete()
{
RequireNotCompleted();
lock (CompletionLock)
{
RequireNotCompleted();
IsCompleted = true;
Monitor.PulseAll(CompletionLock);
}
}
protected void RequireNotCompleted()
{
if (IsCompleted)
{
throw new InvalidOperationException("The operation was already completed");
}
}
protected void Complete(Exception exception)
{
RequireNotCompleted();
lock (CompletionLock)
{
RequireNotCompleted();
Exception = exception;
IsCompleted = true;
Monitor.PulseAll(CompletionLock);
}
}
}
总是工作正常。将项目迁移到.NET 4.5.1后,我们看起来有以下问题:
Wait(Timeout.Inifinte)
,我们知道一个操作已经完成但是Wait
的线程正在等待...如果我们设置超时而不是总是在超时后离开该方法Complete()
等待进入锁定状态 - Monitor.Wait
是否没有回锁?
以下是在工作线程中执行的AsyncCommand
的实现:
internal class AsyncCommand : AsyncOperation
{
private readonly Action<OperationToken> command;
public AsyncCommand(Action<OperationToken> command)
{
command.ThrowIfNull("command");
this.command = command;
}
public void Execute()
{
RequireNotCompleted();
try
{
command(Token);
Complete();
}
catch (Exception ex)
{
Complete(ex);
}
}
}
您是否看到以下代码有任何问题? 什么可能导致这些问题?
闭 上面的实现是正确的。我们遇到了一些与.NET远程连接有关的问题......