2013-04-10 46 views
0

在我的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); 
} 

-------- 
+0

您可以更改「ServiceClient」類的代碼嗎?它應該是固定的東西。 – 2013-04-10 06:57:21

+0

@ MD.Unicorn ServiceClient類是在添加服務引用時由VS自動生成的。 – Raj 2013-05-07 12:59:47

回答

1

第一:

_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); 
} 
+0

感謝您的回覆。你所提出的所有觀點確實都很有用,而且非常有幫助。最後的代碼塊當然是取消訂閱事件處理程序的絕佳方式。但即使在使用這種方法之後,我也面臨同樣的問題,並且兩種回調方法都會一個接一個地被調用。但是,當我使用局部變量而不是使用'this.EMPRepository'來調用'Repository'方法時,它非常有效,因爲這兩個CallBack方法都被傳遞給'Repository'類的不同實例,並且只有attched CallBack方法被觸發。 – Raj 2013-05-07 12:57:10

相關問題