【问题标题】:How to access and modify the mouse cursor outside of the UI thread?如何在 UI 线程之外访问和修改鼠标光标?
【发布时间】:2019-10-24 17:31:59
【问题描述】:

我正在编写一个宏程序,几乎所有东西都设置好了,只需要鼠标控制。问题在于逻辑与 UI 线程分开运行,并且我不知道如何将鼠标从 UI 线程转换为新的。 这是我在没有任何调用的情况下得到的错误。

System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.

我厌倦了通过调用光标来解决这个问题,但它似乎不可调用。 有什么方法可以禁用线程安全,这甚至是个好主意吗?

if (Cursor.Current.Handle.InvokeRequired) //and other variations of it
   this.Invoke(new MethodInvoker(() => this.Cursor = new cursor(Cursor.Current.Handle)));
else this.Cursor = new cursor(Cursor.Current.Handle);

给出错误

'IntPtr' does not contain a definition for 'InvokeRequired' and no accessible extension method 'InvokeRequired' accepting a first argument of type 'IntPtr' could be found (are you missing a using directive or an assembly reference?)

【问题讨论】:

  • 为什么要在后台线程中运行逻辑?难道你不能隔离任何非 UI、长时间运行的操作,并且只在后台线程中运行吗?
  • 您是在 Windows 窗体 中还是在 WPF 中?
  • @ZorgoZ Windows 窗体。
  • @Theodor Zoulias 该逻辑在后台线程中运行,因此它不会锁定主 UI 线程。如果选中复选标记,它可以无限循环运行,并且会锁定 UI。
  • 无限循环是否同样可能在后台线程中运行,或者它只是 UI 线程的问题?

标签: c# multithreading thread-safety cursor-position mouse-cursor


【解决方案1】:

上下文属于Form,而不是光标。这意味着您需要测试对表单实例的调用。但是还有另一个选择:获取同步上下文本身。

var f = new Form();
var ctx = WindowsFormsSynchronizationContext.Current;
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

Action a = () =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        f.Cursor = new Cursor(Cursor.Current.Handle);
    };


Task.Run(async () => {
    await Task.Delay(TimeSpan.FromSeconds(5));
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    ctx.Post(_ => a(), null);
});


Task.Run(async () =>
{
    await Task.Delay(TimeSpan.FromSeconds(10));
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    if (f.InvokeRequired) f.Invoke(a); else a();
});

f.ShowDialog();

【讨论】:

  • 我不熟悉 Action 和 async 方法,所以我希望我做对了。您创建一个新表单,然后运行函数“a”来设置光标。但我不明白你如何使用“if (f.InvokeRequired) f.Invoke(a); else a();”获取光标。
  • @RedXRed 这些只是为了演示。该操作只是您要在 UI 线程上下文中执行的代码。我创建了一个操作以避免重复相同的代码。任务只是强制代码在胎面池上运行。这个 sn-p 实际上是在 LinqPad 中运行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
相关资源
最近更新 更多