事件处理程序未取消订阅
在我的silverlight应用程序中,我将方法GetListCallBack
传递给Repository类中的另一个方法GetEmployees
的委托参数,该参数将该委托作为事件处理程序附加到异步服务调用的完成事件。事件处理程序未取消订阅
EmpViewModel类:
public class EmpViewModel
{
private IRepository EMPRepository = null;
//constructor
public EmpViewModel
{
this.EMPRepository= new Repository();
}
public void GetList()
{
this.EMPRepository.GetEmployees(xyz, this.GetListCallBack);
}
public void GetAnotherList()
{
this.EMPRepository.GetEmployees(pqr, this.GetAnotherListCallBack);
}
private void GetListCallBack(object sender, GetListCompletedEventArgs args)
{
if (args.Error == null)
{
this.collection1.Clear();
this.collection1 = args.Result;
}
else
{
//do sth
}
}
public void GetAnotherListCallback(object sender, GetListCompletedEventArgs args)
{
//do sth with collection1
}
}
仓储类:
public class Repository : IRepository
{
private readonly ServiceClient _client=null ;
public Repository()
{
_client = new ServiceClient(Binding, Endpoint);
}
public void GetEmployees(int xyz, EventHandler<GetListCompletedEventArgs> eventHandler)
{
_client.GetListCompleted -= eventHandler;
_client.GetListCompleted += new EventHandler<GetListCompletedEventArgs>(eventHandler);
_client.GetListAsync(xyz);
}
}
现在,当GetList()
已经完成,然后,如果我调用另一个方法GetAnotherList()
在同一类EmpViewModel
,则该方法的调用在调用GetAnotherListCallBack
之前,再次调用方法GetListCallBack
。
这可能是因为这两种方法都订阅了该事件。
正如你所看到的,我已经明确地从回调事件中取消订阅事件处理器,但仍然调用事件处理器。 任何人都可以请建议我可能会出错的地方吗?
编辑:
当我使用的,而不是使用this.EMPRepository
调用Repository
方法效果很好既是回调方法传递给Repository
类的不同实例,只有attched回调方法被炒鱿鱼
public class EmpViewModel
{
public void GetList()
{
EMPRepository = new Repository();
EMPRepository.GetEmployees(xyz, this.GetListCallBack);
}
public void GetAnotherList()
{
EMPRepository = new Repository();
EMPRepository.GetEmployees(pqr, this.GetAnotherListCallBack);
}
--------
第一:
_client.GetListCompleted += new EventHandler<GetListCompletedEventArgs>(eventHandler);
被(从功能的POI看到nt of view)相同:
_client.GetListCompleted += eventHandler;
而现在你马上看到了问题。您的代码是:
_client.GetListCompleted -= eventHandler;
_client.GetListCompleted += eventHandler;
为什么要删除事件处理程序,如果您将其添加到下一行中。
我想你想删除旧的事件处理程序并添加一个新的。所以你的函数应该让一个委托给旧的事件处理器来删除。类似这样的:
public void GetEmployees(int xyz, EventHandler<GetListCompletedEventArgs> oldEventHandler, EventHandler<GetListCompletedEventArgs> newEventHandler)
{
_client.GetListCompleted -= oldEventHandler;
_client.GetListCompleted += newEventHandler;
_client.GetListAsync(xyz);
}
但是,这甚至可能吗?
如果你有控制权ServiceClient.GetListCompleted
,为什么不删除event
关键字,只是分配一个委托,如:
public void GetEmployees(int xyz, EventHandler<GetListCompletedEventArgs> eventHandler)
{
_client.GetListCompleted = eventHandler;
_client.GetListAsync(xyz);
}
或者......如果委托只调用一次每GetListASync:
public void GetEmployees(int xyz, EventHandler<GetListCompletedEventArgs> eventHandler)
{
_client.GetListCompleted += (sender, args) =>
{
eventHandler(sender, e);
_client.GetListCompleted -= eventHandler;
};
_client.GetListAsync(xyz);
}
感谢您的回复。你所提出的所有观点确实都很有用,而且非常有帮助。最后的代码块当然是取消订阅事件处理程序的绝佳方式。但即使在使用这种方法之后,我也面临同样的问题,并且两种回调方法都会一个接一个地被调用。但是,当我使用局部变量而不是使用'this.EMPRepository'来调用'Repository'方法时,它非常有效,因为这两个CallBack方法都被传递给'Repository'类的不同实例,并且只有attched CallBack方法被触发。 – Raj 2013-05-07 12:57:10
您可以更改“ServiceClient”类的代码吗?它应该是固定的东西。 – 2013-04-10 06:57:21
@ MD.Unicorn ServiceClient类是在添加服务引用时由VS自动生成的。 – Raj 2013-05-07 12:59:47