RedXRed
RedXRed

Reputation: 1

How to access and modify the mouse cursor outside of the UI thread?

I'm writing a macro program, and have almost everything set up expect mouse control. The problem it that the logic is running separate from the UI thread, and that I don't know how to convert the mouse from the UI thread to the new one. This is the error I get without any invoking.

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

I tired to remedy this by invoking the Cursor, but it is not invokable it seems. Is there any way to disable thread safety and would that even be a good idea?

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);

Give the error

'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?)

Upvotes: 0

Views: 1424

Answers (1)

ZorgoZ
ZorgoZ

Reputation: 3569

The context belongs to the Form, not the cursor. That means you need to test for invocation on the form instance. But there is an other option though: grab the synchronization context itself.

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();

Upvotes: 1

Related Questions