在我的C#应用程序中,我有一个服务引用,我一遍又一遍地执行相同的调用。
void GetData()
{
var request = new GetDataRequest { someData = "blabla" } ;
service.GetDataCompleted += (sender, args) =>
{
// do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times
}
service.GetDataAsync(request);
}
void GetData2()
{
var request = new GetDataRequest { someData = "blabla2" } ;
service.GetDataCompleted += (sender, args) =>
{
// do something different here!
}
service.GetDataAsync(request);
}
我怀疑这会以某种方式泄漏,因为我每次都会注册一个新的事件处理程序。 这是真的,如果是的话,我怎么能避免这种情况呢?
答案 0 :(得分:0)
你可以这样做:
void GetData()
{
var request = new GetDataRequest { someData = "blabla" } ;
EventHandler handler = null;
handler = (sender, args) =>
{
// do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times
//remove itself
service.GetDataCompleted -= handler;
};
service.GetDataCompleted += handler;
service.GetDataAsync(request);
}
void GetData2()
{
var request = new GetDataRequest { someData = "blabla2" } ;
EventHandler handler = null;
handler = (sender, args) =>
{
// do something different here!
//remove itself
service.GetDataCompleted -= handler;
};
service.GetDataCompleted += handler;
service.GetDataAsync(request);
}
编辑:关于仅将呼叫同步到其处理程序:如果您紧跟GetData2()
后跟GetData()
,则会从上述代码中获得不可预知的结果。大多数情况下,两个请求都会被调用。
最简单的解决方案是每个service
方法使用单独的GetDataX()
代理对象。这样你就可以同时发出两个请求。
但是,如果您被迫只使用一个代理对象,并进行并发请求 - 则可以调用错误的处理程序。一个选项是您可以使用UserState
对象来标识您的请求,因此即使调用了错误的处理程序,它也可以检测到它被调用了错误的请求。
void GetData()
{
var request = new GetDataRequest { someData = "blabla" } ;
Guid userState = Guid.NewGuid();
EventHandler<GetDataCompletedEventArgs> handler = null;
handler = (sender, args) =>
{
if (userState.Equals(args.UserState))
{
// do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times
//remove itself
service.GetDataCompleted -= handler;
}
};
service.GetDataCompleted += handler;
service.GetDataAsync(request, userState);
}
void GetData2()
{
var request = new GetDataRequest { someData = "blabla2" } ;
Guid userState = Guid.NewGuid();
EventHandler<GetDataCompletedEventArgs> handler = null;
handler = (sender, args) =>
{
if (userState.Equals(args.UserState))
{
// do something different here!
//remove itself
service.GetDataCompleted -= handler;
}
};
service.GetDataCompleted += handler;
service.GetDataAsync(request, userState);
}
现在,如果您发出并发请求,即使两个请求都调用了两个处理程序,只有正确请求的正确代码才会在if
条件内运行。
如果您不想使用UserState
,可以通过某些方法同步呼叫,以便处理程序不会互相跳过。以下是使用Tasks
的一种非阻塞方式,可确保请求一个接一个地发生。
Task<GetDataResponse> GetData()
{
var src = new TaskCompletionSource<GetDataResponse>();
var request = new GetDataRequest { someData = "blabla" } ;
EventHandler handler = null;
handler = (sender, args) =>
{
// do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times
src.SetResult(args.Result);
//remove itself
service.GetDataCompleted -= handler;
};
service.GetDataCompleted += handler;
service.GetDataAsync(request);
return src.Task;
}
Task<GetDataResponse> GetData2()
{
var src = new TaskCompletionSource<GetDataResponse>();
var request = new GetDataRequest { someData = "blabla2" } ;
EventHandler handler = null;
handler = (sender, args) =>
{
// do something different here!
src.SetResult(args.Result);
//remove itself
service.GetDataCompleted -= handler;
};
service.GetDataCompleted += handler;
service.GetDataAsync(request);
return src.Task;
}
在调用方法中,你确保它们被一个接一个地调用:
GetData().ContinueWith( t => GetData2() );