Dispatcher.BeginInvoke: Không thể chuyển đổi lambda thành System.Delegate


81

Tôi đang cố gọi System.Windows.Threading.Dispatcher.BeginInvoke. Chữ ký của phương thức này là:

BeginInvoke(Delegate method, params object[] args)

Tôi đang cố gắng chuyển nó một Lambda thay vì phải tạo một Ủy viên.

_dispatcher.BeginInvoke((sender) => { DoSomething(); }, new object[] { this } );

Nó cho tôi một lỗi trình biên dịch nói rằng tôi

không thể chuyển đổi lambda thành System.Delegate.

Chữ ký của người được ủy quyền nhận một đối tượng làm tham số và trả về giá trị void. Lambda của tôi phù hợp với điều này, nhưng nó không hoạt động. Tôi đang thiếu gì?

Câu trả lời:


70

Vì phương thức này sử dụng System.Delegate , bạn cần cung cấp cho nó một kiểu đại biểu cụ thể, được khai báo như vậy. Điều này có thể được thực hiện thông qua truyền hoặc tạo đại biểu được chỉ định thông qua DelegateType mới như sau:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     new object[] { this } 
  );

Ngoài ra, như SLaks đã chỉ ra, Dispatcher.BeginInvoke lấy một mảng tham số, vì vậy bạn chỉ có thể viết:

_dispatcher.BeginInvoke(
     new Action<MyClass>((sender) => { DoSomething(); }),
     this
  );

Hoặc, nếu DoSomething là một phương thức trên chính đối tượng này:

_dispatcher.BeginInvoke(new Action(this.DoSomething));

3
Nhưng không (x) => {DoSomething (); } khớp với chữ ký của người đại diện? Tôi nghĩ đó là tất cả những gì tôi nên chỉ định.
Micah

@Micah: System.Delegate không có chữ ký - nó chỉ là "bất kỳ đại biểu nào". Bạn cần cung cấp cho nó một kiểu đại biểu với một dấu hiệu. phù hợp với cách sử dụng của bạn.
Reed Copsey

@Reed Nhưng nếu thay cho MyMethod (Action action) (và Action là một đại biểu), tôi có thể gọi MyMethod (() => {DoSomething ();}); Tại sao tôi không thể làm điều tương tự cho BeginInvoke?
Micah

15
@Micah: Thực ra không có chữ ký cho người đại diện, đó là nguyên nhân gây ra vấn đề. InvokeBeginInvokelấy một Delegateđối tượng chung , có thể đại diện cho một phương thức của bất kỳ chữ ký nào. Trong các trường hợp bình thường (khi một đại biểu được đánh mạnh vào một chữ ký cụ thể), trình biên dịch có thể suy ra kiểu đại biểu cụ thể. Đây là lý do tại sao bạn có thể tránh được việc bỏ qua kiểu đại biểu trong các tình huống khác. Tuy nhiên, kể từ khi có không có loại đại biểu thực tế ở đây, trình biên dịch không có cơ sở hợp lý (hoặc, thực sự, thậm chí là một phương tiện ) để sử dụng để chọn một loại đại biểu.
Adam Robinson

2
@Micah: Vì BeginInvoke không được khai báo là BeginInvoke (Action ..), mà là BeginInvoke (System.Delegate, ..) Điều này cho phép nó sử dụng BẤT KỲ loại ủy quyền nào, nhưng bạn phải chỉ định nó một cách rõ ràng.
Reed Copsey

73

Ngắn hơn:

_dispatcher.BeginInvoke((Action)(() => DoSomething()));

8
Ngắn hơn nữa: Tôi không nghĩ bạn cần dấu ngoặc nhọn {} và dấu chấm phẩy xung quanh biểu thức.
sp3ctum

3
Bạn thậm chí không cần (), vì vậy nó có thể được_dispatcher.BeginInvoke((Action)(DoSomething));
mycroes

9

Sử dụng Inline Lambda ...

Dispatcher.BeginInvoke((Action)(()=>{
  //Write Code Here
}));

7

Nếu bạn tham chiếu System.Windows.Presentation.dll từ dự án của mình và thêm using System.Windows.Threadingthì bạn có thể truy cập một phương thức mở rộng cho phép bạn sử dụng cú pháp lambda.

using System.Windows.Threading;

...

Dispatcher.BeginInvoke(() =>
{
});

Tôi không thể làm cho nó hoạt động. Bạn có thể đi vào chi tiết hơn một chút?
Tim Pohlmann

Tôi đã thêm một ví dụ đơn giản. Hãy nhớ tham khảo System.Windows.Presentation.dll
logicnet.dk

Đó chính xác là những gì tôi nhưng bây giờ nó hoạt động ... kỳ lạ. Có lẽ lần trước tôi đã làm sai điều gì đó.
Tim Pohlmann

2

Chúng tôi tạo ra các phương pháp mở rộng cho việc này. Ví dụ

public static void BeginInvoke(this Control control, Action action)
    => control.BeginInvoke(action);

Bây giờ chúng ta có thể gọi nó từ bên trong một hình thức: this.BeginInvoke(() => { ... }).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.