跨线程调用控件
跨线程调用控件,修改控件的属性,比如有一个text控件,用来显示消息
需要使用begininvoke
网上随便找了一个代码,应该是靠谱的,需要使用委托,判断控件是否invokeRequired
用委托,具体代码如下~:
public delegate void MyInvoke(string str);
private void button9_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(fun));
t.Start();
}
private void fun()
{
//_myInvoke("dddd");
SetText("ddd");
}
private void SetText(string s)
{
if (textBox6.InvokeRequired)
{
MyInvoke _myInvoke = new MyInvoke(SetText);
this.Invoke(_myInvoke, new object[] { s });
}
else
{
this.textBox6.Text = s;
}
}
最近发现的牛逼方法
txtbox.Invoke((MethodInvoker)delegate()
{
//在这里写处理方法就可以了
});
逐步 txtbox.Invoke();
txtbox.Invoke((MethodInvoker)delegate(){});
delegate后面的()可以去掉
#region 程序集 System.Windows.Forms.dll, v4.0.30319
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll
#endregion
using System;
namespace System.Windows.Forms
{
// 摘要:
// 表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法。
public delegate void MethodInvoker();
}
MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。
在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。
下面的代码示例演示如何使用 MethodInvoker 以调用更新应用程序窗体的标题栏的方法。
public partial class Form1 : Form
{
public Form1()
{
// Create a timer that will call the ShowTime method every second.
var timer = new System.Threading.Timer(ShowTime, null, 0, 1000);
}
private void ShowTime(object x)
{
// Don't do anything if the form's handle hasn't been created
// or the form has been disposed.
if (!this.IsHandleCreated && !this.IsDisposed)
return;
// Invoke an anonymous method on the thread of the form.
this.Invoke((MethodInvoker) delegate
{
// Show the current time in the form's title bar.
this.Text = DateTime.Now.ToLongTimeString();
});
}
}
英文提示 2022-06-06
System.InvalidOperationException
HResult=0x80131509
Message=Cross-thread operation not valid: Control 'MainForm' accessed from a thread other than the thread it was created on.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Control.set_WindowText(String value)
at System.Windows.Forms.Form.set_WindowText(String value)
at System.Windows.Forms.Control.set_Text(String value)
at System.Windows.Forms.Form.set_Text(String value)
at LisaEncry.MainForm.ATimer_Elapsed(Object sender, ElapsedEventArgs e) in C:\workspace\Company\UK\UKEncryption\SourceCode\LisaEncry\MainForm.cs:line 35
at System.Timers.Timer.MyTimerCallback(Object state)
This exception was originally thrown at this call stack:
[External Code]
LisaEncry.MainForm.ATimer_Elapsed(object, System.Timers.ElapsedEventArgs) in MainForm.cs
[External Code]
Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on [duplicate]
回答1
The data received in your serialPort1_DataReceived
method is coming from another thread context than the UI thread, and that's the reason you see this error.
To remedy this, you will have to use a dispatcher as descibed in the MSDN article:
How to: Make Thread-Safe Calls to Windows Forms Controls
So instead of setting the text property directly in the serialport1_DataReceived
method, use this pattern:
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
So in your case:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
txt += serialPort1.ReadExisting().ToString();
SetText(txt.ToString());
}
回答2
I don't know if this is good enough but I made a static ThreadHelperClass class and implemented it as following .Now I can easily set text property of various controls without much coding .
public static class ThreadHelperClass
{
delegate void SetTextCallback(Form f, Control ctrl, string text);
/// <summary>
/// Set text property of various controls
/// </summary>
/// <param name="form">The calling form</param>
/// <param name="ctrl"></param>
/// <param name="text"></param>
public static void SetText(Form form, Control ctrl, string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (ctrl.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
form.Invoke(d, new object[] { form, ctrl, text });
}
else
{
ctrl.Text = text;
}
}
}
Using the code:
private void btnTestThread_Click(object sender, EventArgs e)
{
Thread demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));
demoThread.Start();
}
// This method is executed on the worker thread and makes
// a thread-safe call on the TextBox control.
private void ThreadProcSafe()
{
ThreadHelperClass.SetText(this, textBox1, "This text was set safely.");
ThreadHelperClass.SetText(this, textBox2, "another text was set safely.");
}
作者:Chuck Lu GitHub |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了