2009-07-22 24 views
51

Điều gì là chính xác hơn và tại sao?MethodInvoker vs Action for Control.BeginInvoke

Control.BeginInvoke(new Action(DoSomething), null); 

private void DoSomething() 
{ 
    MessageBox.Show("What a great post"); 
} 

hoặc

Control.BeginInvoke((MethodInvoker) delegate { 
    MessageBox.Show("What a great post"); 
}); 

tôi kinda cảm thấy như tôi đang làm điều tương tự, vì vậy khi nào là thời điểm thích hợp để sử dụng MethodInvoker vs Action, hoặc thậm chí viết một biểu thức lambda?

EDIT: Tôi biết rằng không có nhiều sự khác biệt giữa việc viết lambda vs Action, nhưng MethodInvoker dường như được thực hiện cho một mục đích cụ thể. Nó có làm gì khác không?

+0

Nhìn này cũng http://mark-dot-net.blogspot.com.uy/2014/07/six-ways-to-initiate-tasks-on-another.html –

Trả lời

71

Cả hai đều đúng, nhưng tài liệu cho Control.Invoke khẳng định rằng:

Các đại biểu có thể là một thể hiện của EventHandler, trong trường hợp này tham số gửi sẽ chứa kiểm soát này, và tham số sự kiện sẽ chứa EventArgs.Empty. Người được ủy quyền cũng có thể là một phiên bản của MethodInvoker hoặc bất kỳ đại biểu nào khác có danh sách tham số void . Cuộc gọi đến số Ủy quyền EventHandler hoặc MethodInvoker được ủy quyền sẽ nhanh hơn cuộc gọi đến một loại đại biểu khác là .

Vì vậy, MethodInvoker sẽ là lựa chọn hiệu quả hơn.

+0

Cảm ơn Jon, nhưng điều gì khiến cho MethodInvoker hiệu quả hơn là gọi hành động mà không có đối số? –

+26

Đơn giản: có vẻ như nó kiểm tra (như các trường hợp đặc biệt) cho cả hai với một/là kiểm tra, và sử dụng Gọi, chứ không phải là DynamicInvoke - đó là ** đáng kể ** nhanh hơn –

2

Đó là vấn đề ưu tiên trong hầu hết các trường hợp, trừ khi bạn có ý định sử dụng lại phương thức DoSomething(). Ngoài ra các chức năng ẩn danh sẽ đặt các biến phạm vi của bạn trên heap, có thể làm cho nó một chức năng đắt tiền hơn.

3

Ngoài ra mỗi MSDN:

MethodInvoker cung cấp một đại biểu đơn giản được sử dụng để gọi một phương pháp với một danh sách khoảng trống tham số. Đại biểu này có thể được sử dụng khi thực hiện cuộc gọi đến phương thức Gọi của điều khiển, hoặc khi bạn cần một đại biểu đơn giản nhưng không muốn tự xác định.

an Mặt khác, hành động có thể mất đến 4 tham số.

Nhưng tôi không nghĩ rằng có bất kỳ sự khác biệt giữa MethodInvokerAction như cả hai đều chỉ đơn giản gói gọn một đại biểu mà không mất một paremter và trả trống

Nếu bạn nhìn vào họ định nghĩa bạn sẽ thấy điều này.

public delegate void MethodInvoker(); 
public delegate void Action(); 

btw bạn cũng có thể viết dòng thứ hai là.

Control.BeginInvoke(new MethodInvoker(DoSomething), null); 
+0

bạn thậm chí có thể viết lại nó như: Control.BeginInvoke (new MethodInvoker (DoSomething)); hoặc Control.BeginInvoke (MethodInvoker mới (() => {DoSomething();})); – juFo

4

Hành động được xác định trong Hệ thống, trong khi MethodInvoker được định nghĩa trong System.Windows.Forms - bạn có thể nên sử dụng Action vì nó di động đến những nơi khác. Bạn cũng sẽ tìm thấy nhiều địa điểm chấp nhận Hành động như một tham số hơn MethodInvoker.

Tuy nhiên, tài liệu chỉ ra rằng các cuộc gọi đến các đại biểu thuộc loại EventHandler hoặc MethodInvoker trong Control.Invoke() sẽ nhanh hơn bất kỳ loại nào khác.

Bên cạnh đó namepsace họ đang ở, tôi không tin rằng có một ý nghĩa chức năng khác biệt giữa hành động và MethodInvoker - họ là về cơ bản cả hai định nghĩa là:

public delegate void NoParamMethod(); 

Là một sang một bên, hành động có một số tình trạng quá tải cho phép các thông số được truyền vào - và nó là chung chung để chúng có thể an toàn.

+4

Và ngược lại, Hành động chỉ được định nghĩa trong .NET 3.5 ... –

8

Tôi thích sử dụng lambdas và hành động/funcs:

Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post"))); 
18

Đối với mỗi giải pháp dưới đây tôi chạy một 131072 (128 * 1024) lặp đi lặp lại (trong một thread tách ra). Các trợ lý hiệu suất VS2010 cho kết quả này:

  • read-only MethodInvoker: 5664,53 (+ 0%)
  • New MethodInvoker: 5828,31 (+ 2,89%)
  • chức năng dàn diễn viên trong MethodInvoker: 5857,07 (3,40 %)
  • read-only hành động: 6467,33 (+ 14,17%)
  • hành động mới: 6.829,07 (+ 20,56%)

Gọi đến một mới Action tại mỗi lần lặp

private void SetVisibleByNewAction() 
    { 
     if (InvokeRequired) 
     { 
      Invoke(new Action(SetVisibleByNewAction)); 
     } 
     else 
     { 
      Visible = true; 
     } 
    } 

Gọi đến một read-only, xây dựng trong constructor, Action tại mỗi lần lặp

// private readonly Action _actionSetVisibleByAction 
    // _actionSetVisibleByAction= SetVisibleByAction; 
    private void SetVisibleByAction() 
    { 
     if (InvokeRequired) 
     { 
      Invoke(_actionSetVisibleByAction); 
     } 
     else 
     { 
      Visible = true; 
     } 
    } 

Gọi đến một mới MethodInvoker tại mỗi lần lặp.

private void SetVisibleByNewMethodInvoker() 
    { 
     if (InvokeRequired) 
     { 
      Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker)); 
     } 
     else 
     { 
      Visible = true; 
     } 
    } 

Gọi đến một read-only, xây dựng trong constructor, MethodInvoker tại mỗi lần lặp

// private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker 
    // _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker; 
    private void SetVisibleByMethodInvoker() 
    { 
     if (InvokeRequired) 
     { 
      Invoke(_methodInvokerSetVisibleByMethodInvoker); 
     } 
     else 
     { 
      Visible = true; 
     } 
    } 

Gọi đến chức năng dàn diễn viên trong MethodInvoker tại mỗi lần lặp

private void SetVisibleByDelegate() 
    { 
     if (InvokeRequired) 
     { 
      Invoke((MethodInvoker) SetVisibleByDelegate); 
     } 
     else 
     { 
      Visible = true; 
     } 
    } 

Ví dụ về cuộc gọi cho giải pháp "Hành động mới":

private void ButtonNewActionOnClick(object sender, EventArgs e) 
    { 
     new Thread(TestNewAction).Start(); 
    } 

    private void TestNewAction() 
    { 
     var watch = Stopwatch.StartNew(); 
     for (var i = 0; i < COUNT; i++) 
     { 
      SetVisibleByNewAction(); 
     } 
     watch.Stop(); 
     Append("New Action: " + watch.ElapsedMilliseconds + "ms"); 
    } 
0

Đừng quên bằng cách nào đó kiểm tra xem điều khiển có sẵn tại thời điểm này không, để tránh lỗi ở dạng đóng.

if(control.IsHandleCreated) 
control.BeginInvoke((MethodInvoker)(() => control.Text="check123")); 
Các vấn đề liên quan