我们有一个客户端类,它扩展了 BaseClass 。
BaseClass 有以下方法:
protected void Proxy()
{
Error = null;
_proxy = new WebServiceClient<T>(_fullURL);
Error = _proxy.Error;
}
protected virtual void Cleanup()
{
if (_proxy != null)
{
_proxy.Dispose();
_proxy = null;
}
}
客户端包含多个并行调用的操作。 客户端不是Singleton,我们每次都会生成一个实例。
操作如下:
public void OperationAsync(Action<BaseResult> callback)
{
TaskCompletionSource<String> taskSrc = new TaskCompletionSource<String>();
Task<String> tsk = taskSrc.Task;
try
{
Proxy();
ThreadPool.QueueUserWorkItem(t =>
{
try
{
String result = _proxy.Channel.ExecuteOperation(SecurityToken());
taskSrc.SetResult(result);
}
catch (Exception ex)
{
taskSrc.SetException(ex);
}
});
tsk.Wait();
BaseResult r = new BaseResult();
r.Value = tsk.Result;
r.Error = tsk.Exception;
Cleanup();
if (callback != null)
{
callback(r);
}
}
catch (Exception ex)
{
FileManager.Log(ex);
}
}
如您所见,每项操作都会调用代理和 CleanUp 操作。
我们还没有发现任何行为模式,但有时(可能每天一次)我们在日志文件中看到此错误:
发生了一个或多个错误.BurnerException:System.ObjectDisposedException:无法访问已处置的对象。 对象名称:'System.ServiceModel.Channels.ServiceChannel'。
任何具体操作都不会发生。它总是变化的。 我相信代理需要在构造函数和清理期间完成处理,但它意味着要改变一些事情,我想确定。
我真的很感激如何改进它。
答案 0 :(得分:1)
由于您的原始代码正在调用tsk.Wait();
,因此您在后台线程上运行代理代码时阻止了调用线程。没有任何好处,可能会增加这样的开销。
所以,这是如何防止竞争条件:
public void OperationAsync(Action<BaseResult> callback)
{
try
{
var r = new BaseResult();
using (var proxy = new WebServiceClient<T>(_fullURL))
{
try
{
r.Value = proxy.Channel.ExecuteOperation(SecurityToken());
}
catch (Exception ex)
{
r.Error = ex;
}
}
if (callback != null)
{
callback(r);
}
}
catch (Exception ex)
{
FileManager.Log(ex);
}
}