2009-04-23 21 views
12

C# içinde bulduğumdan, Control.Invoke yöntemi, giriş parametresi olmayan bir temsilci kullanmanız gerekir. Bunun etrafında bir yolu var mı? Kullanıcı Arabirimini başka bir iş parçacığından güncellemek ve dizge parametrelerine iletmek için bir yöntem çağırmak isterim.Control.Invoke Giriş Parametreleri

cevap

22

Hangi C# sürümünü kullanıyorsunuz? C# 3.5 kullanıyorsanız, parametrelerin geçişini önlemek için kapaklar kullanabilirsiniz.

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()); 
    } 
} 

ile güvenle şimdi kod yürütmesini önemsiz hale gelir. C# 2.0 ile

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()); 

basit Bunu kullanarak
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; 
    } 
    } 
} 

az önemsiz hale gelir, ancak daha fazla parametre için daha geri aramalar tanımlamak zorunda.

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

Ben Samuel'in (mükemmel) yaklaşımı daha da itilebilir düşünüyorum:

Uzatma Yöntemi:

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

Formu kodu:

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

Luke gibi diyor, Control.I kullanın Böyle nvoke ... Bir formda Örneğin

: Sonra

passMessage = new DelegatePassMessages (this.MessagesIn); 

verilerin almaya MessagesIn fonksiyonu: Sonra

public void MessagesIn(string name, int value) 
{ 

} 

işinin müteahhidi olarak

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

public DelegatePassMessages passMessage; 

Verilerinizi formunuza iletmek için:

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

.Net 2.0 için bir MethodInvoker Temsilcisine sarılmış anonim yöntemlerle zarif bir yöntem bulundu. Bu şekilde, her zaman kendi delegelerini tanımlamaya gerek yoktur.Örnek:

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

Neden

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

Biraz daha olasılıklar:

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

veya

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

hatta

01 İlk seçenek en iyi olanı olduğu için, MethodInvoker bu amaçlar için tasarlandığından ve daha iyi bir performans gösterdiğinden,

.

1

Burada, Invoke() uzantısı + bir giriş parametresiyle lambda ifadeleri kullanmaya gidiniz.

kullanılması: aksiyon (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); 
     } 
    }