注意:系列文章的一部分:C#: Accessing form members from another class和How to access form objects from another cs file in C#。
您好,
想法是在TCP客户端接收/发送数据包时使用备忘录通知用户。
经过几次修复,最合适的解决方案似乎就是这个
public string TextValue
{
set
{
this.Memo.Text += value + "\n";
}
}
这就是它被称为
的方式 var form = Form.ActiveForm as Form1;
if(form != null)
form.TextValue = "Test asdasd";
然而,由于不安全的线程调用,调用代码会引发异常。我在msdn找到了一个解决方案,但我似乎无法获得他们在那里使用的方法。
这是我的翻拍,但不起作用。
private void SetTextMemo(string txt)
{
if(this.Memo.InvokeRequired)
{
this.Invoke(SetTextMemo,txt); //error here
}
else
{
this.Memo.Text += txt + "\n";
}
}
错误:
参数'1':无法从'方法组'转换为'System.Delegate'
参数'2':无法从'string'转换为'object []'
基本上,我正在尝试使用Invoke从另一个线程访问备忘录(或者更可能是说,在备忘录中添加文本)。我以前从未使用它,也许这就是我误解了我的错误的原因。
答案 0 :(得分:11)
简单的方法是:
this.Invoke((MethodInvoker)delegate {
this.Memo.Text += txt + "\n";
});
使用匿名方法进行内联工作。由于你期望在另一个线程上,你也可以只调用Invoke - 它甚至可以从UI线程安全。
答案 1 :(得分:1)
如果您正在使用C#3.0和3.5框架,请尝试以下
if ( this.Memo.InvokeRequired ) {
this.Invoke((Action)(() => SetTextMemo(txt)));
}
答案 2 :(得分:1)
您的实现假定该方法不会无限递归,因为InvokeRequired属性的行为将阻止它。这种假设可能是正确的,但编码函数以完全避免这种可能性是没有问题的。这是我的建议:
private void SetMemo(string txt)
{
Memo.Text = txt;
}
private delegate void MemoSetter(string txt);
public void ThreadSafeSet(string txt)
{
Invoke(new MemoSetter(SetMemo), txt);
}
答案 3 :(得分:0)
我曾经处理过所有这些跨线程的业务,但最近我选择了AOP,在那里你只需装饰一个在UI线程上执行的方法。这是一个例子(来自PostSharp):
public class FormsThreadAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
Form f = (Form)eventArgs.Delegate.Target;
if (f.InvokeRequired)
f.Invoke(eventArgs.Delegate, eventArgs.GetArgumentArray());
else
eventArgs.Proceed();
}
}