2009-04-23 26 views
12

Từ những gì tôi đã tìm thấy trong C#, phương thức Control.Invoke yêu cầu bạn sử dụng một đại biểu không có tham số đầu vào. Có cách nào để khắc phục điều này? Tôi muốn gọi một phương thức để cập nhật giao diện người dùng từ một luồng khác và chuyển đến các tham số chuỗi cho nó.Control.Invoke với tham số đầu vào

Trả lời

22

Bạn đang sử dụng phiên bản C# nào? Nếu bạn đang sử dụng C# 3.5, bạn có thể sử dụng các bao đóng để tránh truyền các thông số.

Với C# 3,5
public static class ControlExtensions 
{ 
    public static TResult InvokeEx<TControl, TResult>(this TControl control, 
              Func<TControl, TResult> func) 
    where TControl : Control 
    { 
    return control.InvokeRequired 
      ? (TResult)control.Invoke(func, control) 
      : func(control); 
    } 

    public static void InvokeEx<TControl>(this TControl control, 
             Action<TControl> func) 
    where TControl : Control 
    { 
    control.InvokeEx(c => { func(c); return c; }); 
    } 

    public static void InvokeEx<TControl>(this TControl control, Action action) 
    where TControl : Control 
    { 
    control.InvokeEx(c => action()); 
    } 
} 

an toàn cách gọi mã bây giờ trở nên tầm thường.

this.InvokeEx(f => f.label1.Text = "Hello World"); 
this.InvokeEx(f => this.label1.Text = GetLabelText("HELLO_WORLD", var1)); 
this.InvokeEx(() => this.label1.Text = DateTime.Now.ToString()); 

Với C# 2.0 nó trở nên ít tầm thường
public class MyForm : Form 
{ 
    private delegate void UpdateControlTextCallback(Control control, string text); 
    public void UpdateControlText(Control control, string text) 
    { 
    if (control.InvokeRequired) 
    { 
     control.Invoke(new UpdateControlTextCallback(UpdateControlText), control, text); 
    } 
    else 
    { 
     control.Text = text; 
    } 
    } 
} 

Sử dụng nó đơn giản, nhưng bạn phải xác định hơn callbacks cho các thông số hơn.

this.UpdateControlText(label1, "Hello world"); 
1

Tôi nghĩ (xuất sắc) Cách tiếp cận của Samuel có thể được đẩy thậm chí nhiều hơn:

Phương pháp mở rộng: Mã

public static void ExecuteAsync<TControl>(this TControl control, Action action) 
where TControl : Control 
{ 
    new Thread(() => 
    { 
    control.Invoke(action); 
    }) 
    .Start(); 
} 

Mẫu:

private void doStuff() 
{ 
    this.ExecuteAsync(() => 
    { 
    // Do your stuff in a separate thread 
    // but having full access to local or instance variables. 

    // No (visible) threading code needs to be used here. 
    }); 
} 
6

Như Luke nói, sử dụng Control.I nvoke như thế này ...

Ví dụ trong một hình thức:

public delegate void DelegatePassMessages(string name, int value); 

public DelegatePassMessages passMessage; 

Trong contructor:

passMessage = new DelegatePassMessages (this.MessagesIn); 

Sau đó, chức năng MessagesIn để nhận dữ liệu:

public void MessagesIn(string name, int value) 
{ 

} 

Sau đó, để chuyển dữ liệu đến biểu mẫu của bạn:

formName.Invoke(formName.passMessage, new Object[] { param1, param2}); 
0

Tìm thấy một phương thức thanh lịch cho .net 2.0 với các phương thức ẩn danh được bao bọc trong một MethodInvoker Delegate. Bằng cách đó, không cần phải định nghĩa các đại biểu riêng.Ví dụ:

private void InitUI(Guid id, string typename) 
    { 
     MethodInvoker inv = delegate{tvMatrix.Nodes[0].Nodes.Add(id.ToString(), typename);}; 
     tvMatrix.Invoke(inv); 
    } 
0

Tại sao không

tvMatrix.Invoke((MethodInvoker) (() => { 
    tvMatrix.Nodes[0].Nodes.Add(id.ToString(), typename); 
})); 
7

Một số chi tiết khả năng:

this.Invoke(new MethodInvoker(() => this.DoSomething(param1, param2))); 

hoặc

this.Invoke(new Action(() => this.DoSomething(param1, param2))); 

hoặc thậm chí

this.Invoke(new Func<YourType>(() => this.DoSomething(param1, param2))); 

nơi tùy chọn đầu tiên là tùy chọn tốt nhất, vì MethodInvoker được khái niệm cho mục đích đó và có hiệu suất tốt hơn.

1

Ở đây, bạn sử dụng biểu thức lambda với phần mở rộng Invoke() + tham số đầu vào.

Sử dụng: hành động (STARS db)

_ccb.GetImagerFRU_PartNbr().Invoke(new Action<STARS>(dbase => _ccb.GetImagerFRU_PartNbr().Text = dbase.PartNumber(serial) ?? String.Empty), db); 
0
private void ppTrace(string tv) 
    { 
     if (_Txb1.InvokeRequired) 
     { 
      _Txb1.Invoke((Action<string>)ppTrace, tv); 
     } 
     else 
     { 
      _Txb1.AppendText(tv + Environment.NewLine); 
     } 
    } 
Các vấn đề liên quan