Label从另一个线程更新a的最简单方法是什么?
我有一Form对thread1,并从我开始另一个线程(thread2).虽然thread2在处理一些文件,我想更新Label在Form用的当前状态thread2的工作.
我怎样才能做到这一点?
只是想知道BeginInvoke()和之间的区别Invoke()是什么?
主要是每个人将用于什么.
编辑:创建一个线程对象和调用invoke并只调用BeginInvoke()一个委托有什么区别?或者他们是一样的吗?
我想从微控制器发送温度值,使用UART到C#接口和显示温度开启Label.Content.这是我的微控制器代码:
while(1) {
key_scan(); // get value of temp
if (Usart_Data_Ready())
{
while(temperature[i]!=0)
{
if(temperature[i]!=' ')
{
Usart_Write(temperature[i]);
Delay_ms(1000);
}
i = i + 1;
}
i =0;
Delay_ms(2000);
}
}
Run Code Online (Sandbox Code Playgroud)
我的C#代码是:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
txt += serialPort1.ReadExisting().ToString();
textBox1.Text = txt.ToString();
}
Run Code Online (Sandbox Code Playgroud)
但是异常出现了" 跨线程操作无效:控制'textBox1'从一个线程访问,而不是在它创建的线程上 "请告诉我如何从我的微控制器获取温度字符串并删除此错误!
我有一个类似于Greg D讨论的SafeInvoke Control扩展方法(减去IsHandleCreated检查).
我从System.Windows.Forms.Form以下地址调用它:
public void Show(string text) {
label.SafeInvoke(()=>label.Text = text);
this.Show();
this.Refresh();
}
Run Code Online (Sandbox Code Playgroud)
有时(此调用可能来自各种线程),这会导致以下错误:
System.InvalidOperationException发生了
Message="在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke."
Source="System.Windows.Forms"Run Code Online (Sandbox Code Playgroud)StackTrace: at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) at System.Windows.Forms.Control.Invoke(Delegate method) at DriverInterface2.UI.WinForms.Dialogs.FormExtensions.SafeInvoke[T](T control, Action`1 action) in C:\code\DriverInterface2\DriverInterface2.UI.WinForms\Dialogs\FormExtensions.cs:line 16
发生了什么,我该如何解决?我知道这不是形式创建的问题,因为有时它会工作一次并且下次失败,那么问题是什么呢?
PS.我真的很擅长WinForms,有没有人知道一系列很好的文章解释整个模型以及如何使用它?
我无法弄清楚如何使C#Windows窗体应用程序从一个线程写入文本框.例如,在Program.cs中,我们有标准的main()来绘制表单:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Run Code Online (Sandbox Code Playgroud)
然后我们在Form1.cs中:
public Form1()
{
InitializeComponent();
new Thread(SampleFunction).Start();
}
public static void SampleFunction()
{
while(true)
WindowsFormsApplication1.Form1.ActiveForm.Text += "hi. ";
}
Run Code Online (Sandbox Code Playgroud)
我完全错了吗?
UPDATE
以下是bendewey提供的工作代码示例:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
new Thread(SampleFunction).Start();
}
public void AppendTextBox(string value)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(AppendTextBox), new object[] {value});
return;
}
textBox1.Text += value;
}
void SampleFunction()
{
// Gets executed on a seperate thread and
// doesn't block the …Run Code Online (Sandbox Code Playgroud) 我在C#app中有简单的方法,它从FTP服务器中挑选文件并解析它并将数据存储在DB中.我希望它是异步的,以便用户在App上执行其他操作,一旦完成解析,他必须得到消息"解析完成".
我知道它可以通过异步方法调用实现,但我不知道该怎么做才能有人帮助我吗?
有谁知道如何在控制台应用程序中使用RegisterHotKey/UnregisterHotKey API调用?我假设设置/删除热键是相同的,但是如何在按下键时收到回叫?
我看到的每个例子都是针对Winforms和使用的protected override void WndProc(ref Message m){...},我无法使用.
SetupHotkey一个不同的线程也没有任何反应.有什么想法吗?
class Program
{
static void Main(string[] args)
{
new Hud().Init(args);
}
}
class Hud
{
int keyHookId;
public void Init(string[] args)
{
SetupHotkey();
InitPowershell(args);
Cleanup();
}
private void Cleanup()
{
HotKeyManager.UnregisterHotKey(keyHookId);
}
private void SetupHotkey()
{
keyHookId = HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Control);
HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyManager_HotKeyPressed);
}
void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
{
//never executed
System.IO.File.WriteAllText("c:\\keyPressed.txt", "Hotkey pressed");
}
private static void InitPowershell(string[] args)
{
var config = …Run Code Online (Sandbox Code Playgroud) 我知道之前已经问过这个问题,但我正在寻找一种方法:
这是我到目前为止,但我想删除Windows窗体引用.有任何想法吗?
public delegate void SafeInvokeDelegate(System.Action action);
public class SafeInvoke
{
private readonly System.Windows.Forms.Control _threadControl;
public SafeInvoke()
{
_threadControl = new System.Windows.Forms.Control();
}
public void Invoke(System.Action action)
{
if (_threadControl.InvokeRequired)
_threadControl.Invoke(new SafeInvokeDelegate(Invoke), new object[] {action});
else if (action != null) action();
}
}
Run Code Online (Sandbox Code Playgroud)
上面的类可能会这样使用:
SafeInvoke _safeInvoker = new SafeInvoke();
void SafeClearItems()
{
_safeInvoker.Invoke(delegate
{
listView1.Items.Clear();
});
}
Run Code Online (Sandbox Code Playgroud)
我如何删除SafeInvoke类中的System.Windows.Forms.Control但保持相同的功能?
可能重复:
跨线程操作无效:从创建它的线程以外的线程访问控件
好的,我知道为什么这会给我这个错误:
跨线程操作无效:控制从其创建的线程以外的线程访问的"Form1".
但是......我怎样才能使这个可行?
System.Threading.Thread t = new System.Threading.Thread(()=>
{
// do really hard work and then...
listView1.Items.Add(lots of items);
lots more UI work
});
t.Start();
Run Code Online (Sandbox Code Playgroud)
我不关心Thread何时或如何完成,所以我并不关心任何花哨或过于复杂的atm,除非在新的Thread中使用UI时会更容易.
我正在运行的大型操作上收到以下消息:
CLR无法从COM上下文0x1fe458过渡到COM上下文0x1fe5c8 60秒.拥有目标上下文/公寓的线程很可能是在非抽空等待或处理非常长时间运行的操作而不抽取Windows消息.这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随时间不断累积.为了避免这个问题,所有单线程单元(STA)线程都应该使用抽取等待原语(例如CoWaitForMultipleHandles)并在长时间运行操作期间定期泵送消息.
如何发送Windows消息,以便在长时间操作中不再出现此错误?
c# ×9
.net ×4
winforms ×4
invoke ×3
asynchronous ×1
begininvoke ×1
delegates ×1
message-pump ×1
pinvoke ×1
uart ×1
winapi ×1