2015-11-25 23 views
6

Trong mã của tôi, tôi cần phải hủy đăng ký và đăng ký một xử lý sự kiện, này hoạt động hoàn hảo:Làm cách nào để hủy đăng ký và đăng ký trình xử lý Sự kiện đang chờ xử lý?

_favoritsImageView.Click -= _favoritsImageView_Click(this, new CustomeClickEventArgs(item)); 
_favoritsImageView.Click += _favoritsImageView_Click(this, new CustomeClickEventArgs(item)); 
void _favoritsImageView_Click(object sender, CustomeClickEventArgs e) 
{ 
     // handles the event 
} 

Nhưng đối với một awaitable handler sự kiện tôi phải sử dụng cú pháp sau:

_favoritsImageView.Click -= async (s, e) => 
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); }; 

_favoritsImageView.Click += async (s, e) => 
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); }; 

async Task _favoritsImageView_ClickAsync(object sender, CustomeClickEventArgs e) 
{ 
     // does async task 
} 

này không không làm việc. Bởi vì các phương thức nặc danh không có cùng tham chiếu. Vì vậy, dòng đầu tiên không hủy đăng ký trình xử lý đã đăng ký. Và cuối cùng dòng thứ hai thêm một trình xử lý sự kiện bổ sung cho nhấp chuột.

Tôi cần sử dụng cú pháp nào để thêm và xóa trình xử lý sự kiện không đồng bộ?

Cảm ơn mọi đề xuất.

+0

Tôi nhầm lẫn, cú pháp mà bạn nói "hoạt động hoàn hảo" không thể hoạt động. Trừ khi '_favoritsImageView_Click' là một phương thức trả về một đại biểu, điều này sẽ thực sự kỳ lạ. – svick

+0

@svick Tôi đã thêm '_favoritsImageView_Click' vào mã mẫu. Whats sai với điều đó ?? –

+0

Có gì sai là dòng '_favoritsImageView.Click + = _favoritsImageView_Click (điều này, CustomeClickEventArgs mới (mục));' sẽ không biên dịch. – svick

Trả lời

5

Which syntax do I need to use to add and remove an async event handler?

Cú pháp tương tự như bạn cần sử dụng với trình xử lý sự kiện thông thường. Bạn cần phải lưu các đại biểu ở đâu đó vì vậy bạn sau này có thể bỏ đăng ký nó:

private EventHandler eventHandler = 
          new EventHandler(async (s, e) => await FooAsync(s, e)); 

public async void SomeOtherEventHandler() 
{ 
    var m = new M(); 
    m.X += eventHandler; 
    m.OnFoo(); 
    m.X -= eventHandler; 
    m.OnFoo(); 
} 

public async Task FooAsync(object sender, EventArgs e) 
{ 
    await Task.Delay(1000); 
    Debug.WriteLine("Yay event handler"); 
} 

public class M 
{ 
    public event EventHandler X; 
    public void OnX() 
    { 
     // If you're using C#-6, then X?.Invoke(null, EventArgs.Empty); 

     var localX = X; 
     if (localX != null) 
      localX(null, EventArgs.Empty); 
    } 
} 

Sửa:

@svick gợi ý có lẽ giải pháp khác, chỉ đơn giản là làm cho phương pháp async void và đăng ký trực tiếp, mà chắc chắn là ngắn hơn:

public async void SomeOtherEventHandler() 
{ 
    var m = new M(); 
    m.X += FooAsync; 
    m.OnFoo(); 
    m.X -= FooAsync; 
    m.OnFoo(); 
} 

public async void FooAsync(object sender, EventArgs e) 
{ 
    await Task.Delay(1000); 
    Debug.WriteLine("Yay event handler"); 
} 
+0

Bạn chỉ cần lưu đại biểu nếu trình xử lý sự kiện của bạn là lambda. Tôi nghĩ rằng nói chung, một giải pháp tốt hơn là viết trình xử lý sự kiện như một phương thức (phương thức 'async void' trong trường hợp này), điều này sẽ làm cho mã đơn giản hơn. – svick

+0

@svick Đó là một ý tưởng hay. Đã thêm phiên bản khác với đăng ký trực tiếp. –

+0

Tôi nghĩ rằng nó có thể là tuyệt vời để biết sự khác biệt giữa một nhiệm vụ trở lại và một void trở lại trong trường hợp này là gì, và tại sao câu trả lời @svick là tốt :) https://stackoverflow.com/a/8043882/6400617 –

1

mã đồng bộ trông giống như sau:

private void FavoritsImageView_Click(object sender, CustomeClickEventArgs args) 
{ 
    // your synchronous code here 
} 

… 

_favoritsImageView.Click += FavoritsImageView_Click; 
_favoritsImageView.Click -= FavoritsImageView_Click; 

Phiên bản async trông gần như giống nhau, bạn chỉ cần thêm async đến phương pháp:

private async void FavoritsImageView_Click(object sender, CustomeClickEventArgs args) 
{ 
    // your asynchronous code here 
} 

… 

_favoritsImageView.Click += FavoritsImageView_Click; 
_favoritsImageView.Click -= FavoritsImageView_Click; 

Lưu ý rằng một event handler là khá nhiều nơi duy nhất bạn nên sử dụng async void. Trong hầu hết các trường hợp khác, phương thức void đồng bộ phải được chuyển đổi thành phương thức async Task.

+0

I đã thử nó rồi. Lỗi trình biên dịch: Không thể chuyển đổi hoàn toàn kiểu 'void' thành 'System.EventHandler' –

+0

@ a.toraby Tôi nhận được lỗi đó khi tôi sử dụng cú pháp '+ = FavoritsImageView_Click (this, new CustomeClickEventArgs (item));'. Nhưng đó không phải là những gì tôi đã gợi ý. – svick

+0

@downvoter Chăm sóc để giải thích những gì bạn nghĩ là sai với câu trả lời của tôi? – svick

Các vấn đề liên quan