【问题标题】:Eventhandler not getting unsubscribed事件处理程序没有被取消订阅
【发布时间】:2013-04-10 06:52:00
【问题描述】:

在我的 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() 的调用完成后,如果我在同一类 EmpViewModel 中调用另一个方法 GetAnotherList(),则在调用 GetAnotherListCallBack 之前再次调用 GetListCallBack 方法。

这可能是因为两种方法都订阅了事件。

如您所见,我已从回调事件中明确取消订阅事件处理程序,但事件处理程序仍在被调用。 谁能建议我哪里出错了?

编辑:

当我使用局部变量而不是使用 this.EMPRepository 来调用 Repository 方法时,它运行良好,因为两个 CallBack 方法都被传递给 Repository 类的不同实例,并且只有附加的 CallBack 方法被触发

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);
}  

--------

【问题讨论】:

  • 你能更改ServiceClient类的代码吗?这是应该解决的问题。
  • @MD.Unicorn ServiceClient 类在添加服务引用时由 VS 自动生成。

标签: c# silverlight events delegates


【解决方案1】:

第一:

_client.GetListCompleted += new EventHandler<GetListCompletedEventArgs>(eventHandler);

是(从功能的角度来看)相同:

_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' 类的不同实例,并且只有附加的 CallBack 方法被触发。
猜你喜欢
  • 1970-01-01
  • 2012-06-15
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多