【问题标题】:how to run background Thread that needs to access to ui thread如何运行需要访问ui线程的后台线程
【发布时间】:2019-02-13 05:50:30
【问题描述】:

我期待在我的程序中添加鼠标位置检查模块。 UI有两个Textbox来打印X和Y。它应该异步打印光标位置。

我尝试了BeginInvoke/Invoke,Thread.isBackgroud = true,BackgroundWorker,但这些都没有帮助。

Thread/BackgroundWorker 不断发生

跨线程错误(如预期),

并且BeginInvoke/Invoke 有异步问题:UI 线程一直死机。

我也尝试了mousemove 事件,这可行,但是当光标超出表单边界时,位置跟踪停止。

delegate void MP();
private void tracktoggle() {
    MP mp = printMousePosition;
    BeginInvoke(mp); // Or Invoke(mp);
}

private void printMousePosition() {
    while(true) {
       this.Xtext.Text = Mouseposition.X.ToString();
       this.Ytext.Text = Mouseposition.Y.ToString();
    }
}

此代码使 UI 线程处于阻塞状态。

private async void tracktoggle() {
    Task T = new Task(() => { printMousePosition(); });
    await T;
}

private void printMousePosition() {
    while(true) {
       this.Xtext.Text = Mouseposition.X.ToString();
       this.Ytext.Text = Mouseposition.Y.ToString();
    }
}

这是带有 async/await 的代码。不会阻塞 UI 线程,但文本框没有得到更新。 我认为 BeginInvoke 是 Invoke 的异步版本 :( 不起作用

希望在不阻塞 UI 线程的情况下异步打印鼠标位置。

【问题讨论】:

  • printMousePosition() 中的无限 while 循环,你 BeginInvoke 只会导致 UI 完全冻结。您可能希望用报告进度的BackgroundWorker 替换您的设计。更容易
  • ㄴ 谢谢,我会用 BackgroundWorker 集重试
  • 虽然BeginInvoke 是异步的,但你是对的。但是,它最终调用的任何方法都不能是无限循环。它必须给 UI 一个自我更新的机会
  • ㄴ 哦.. 好的,我明白了
  • how to run background Thread that needs to access to ui thread 你可以使用异步等待模式,它会处理延续。

标签: c# .net multithreading winforms


【解决方案1】:

我发现最好的解决方案是使用 user32.dll 设置 WindowsHook。

[DllImport("user32.dll", CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
public static extern int SetWindowsHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

///On the Code 14 is low level mouse hooking id
HookID = SetWindowsHookEx(14, MouseEventFunc, (IntPtr)0, 0/*should be 0, cause we are trying to make global hook);

private void int MouseEventFunc(int nCode, IntPtr w, IntPtr l) {
{
     this.MouseX.Text = MousePosition.X.ToString();
     this.MouseY.Text = MousePosition.Y.ToString();
     return CallNextHookEx(HookID, nCode, w, l);
}

这个 sn-p 可以很好地获取/更新 TextBox。

有人有这个问题,试试这个解决方案

【讨论】:

    猜你喜欢
    • 2020-10-13
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    相关资源
    最近更新 更多