Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async P/Invoke calls

Tags:

c#

I'm working on a wrapping library for a robot controller, that mostly relies on P/Invoke calls.

However, a lot of the functionality for the robot, such as homing, or movement, takes quite a while, and do thread locks while running.

So I'm wondering how I can wrap the functionality in a async manner, so the calls don't block my UI thread. My idea so far is to use Tasks, but I'm not really sure it's the right approach.

public Task<bool> HomeAsync(Axis axis, CancellationToken token)
{
    return Task.Factory.StartNew(() => Home(axis), token);
}

Most of the MSDN articles on the Async model in .NET as of right now, mostly is relaying on libraries already having Async functionality (such as File.BeginRead and so on). But I can't seem to find much information on how to actually write the async functionality in the first place.

like image 948
Claus Jørgensen Avatar asked Feb 03 '23 01:02

Claus Jørgensen


2 Answers

After some great discussion, I think something like this will be the golden middleway.

public void HomeAsync(Axis axis, Action<bool> callback)
{
    Task.Factory
        .StartNew(() => Home(axis))
        .ContinueWith(task => callback(task.Result));
}

This is using the best of both worlds, I think.

like image 147
Claus Jørgensen Avatar answered Feb 05 '23 13:02

Claus Jørgensen


Have you ever tried async delegates? I believe there is nothing simpler than it.

If your thread-blocking method is void Home(Axis) you have first to define a delegate type, ie. delegate void HomeDelegate(Axis ax), then use the BeginInvoke method of a new instance of HomeDelegate pointing to the address of Home method.

[DllImport[...]] //PInvoke
void Home(Axis x);

delegate void HomeDelegate(Axis x);

void main()
{
    HomeDelegate d = new HomeDelegate(Home);
    IAsyncResult ia = d.BeginInvoke(axis, null, null);
    [...]
    d.EndInvoke(ia);
}

Please bear in mind that using the EndInvoke somewhere (blocking the thread until the method is finally over, maybe in conjunction with polling of IAsyncResult.Completed property) is very useful to check if your async task has really been completed. You might not want your robot to open its arm and leave a glass until the glass is over the table, you know ;-)

like image 21
usr-local-ΕΨΗΕΛΩΝ Avatar answered Feb 05 '23 15:02

usr-local-ΕΨΗΕΛΩΝ