0

I'm afraid the more I read, the more baffled I get. I think I need a real world example. I'm stuck in some code in a MVVM WPF app. How do I get NetworkPlaces running asyncronously so it doesn't block the UI thread? I've tried loads of different combinations of async, task and await.

A lot of the examples seem to use 'end' methods that have asynchronous methods within it such as .ReadToEndAsync or .GetStringAsync. One advisory (and UI freeze) I kept getting was about NetworkPlaces not having an Async method.

Here's my illustration code at the moment. I'd be grateful if someone could show mw some working code:

public RelayCommand ScanForDevicesCMD { get; private set; }


public MainVM()
{
    ScanForDevicesCMD = new RelayCommand(ScanForDevices, CanScanForDevices);
}

public async void ScanForDevices(object obj)
{
    Debug.WriteLine("SCAN STARTED");

    Task task = NetworkPlaces();
    await task;
    Debug.WriteLine("SCAN STOPPED");
}

public Task NetworkPlaces()
{
    ShellNetworkComputers shellNetworkComputers = new ShellNetworkComputers();
    foreach (string snc in shellNetworkComputers)
    {
        Debug.WriteLine(snc);
    }
    return Task.CompletedTask;           
}
stigzler
  • 793
  • 2
  • 12
  • 29

1 Answers1

2

You can run synchronous code as a Task.

Change your method to this:

public void NetworkPlaces()
{
    ShellNetworkComputers shellNetworkComputers = new ShellNetworkComputers();
    foreach (string snc in shellNetworkComputers)
    {
        Debug.WriteLine(snc);
    }         
}

And call it like this:

await Task.Run(() => {
    NetworkPlaces();
});

Update: Make sure that NetworkPlaces() doesn't do any UI work (e.g. user interaction) itself.

Julian
  • 5,290
  • 1
  • 17
  • 40
  • That's a fact, yes, but how do you infer from the question or my answer that this might be the case? I merely made a few changes based on the request: "How do I get NetworkPlaces running asyncronously so it doesn't block the UI thread?" That doesn't mean that `NetworkPlaces` includes UI interaction. – Julian Oct 22 '22 at 19:00
  • This was a really helpful answer, thanks. I'm also migrating over from vb to c# - is that some form of lambda? – stigzler Oct 22 '22 at 19:04
  • It's an anonymous function created via a statement lambda. The anonymous function in this case is treated as an Action, c.f.: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=net-7.0#system-threading-tasks-task-run(system-action) – Julian Oct 22 '22 at 19:20
  • 1
    *"Make sure that NetworkPlaces() doesn't do any blocking UI work"* -- This implies that doing **non**-blocking UI work is OK. It's not OK, because all UI components are supposed to be manipulated exclusively by the UI thread. And the `Task.Run` runs on the `ThreadPool`. – Theodor Zoulias Oct 23 '22 at 09:33
  • Right again, fixed it @TheodorZoulias. However, one remark: UI work can be delegated to the MainThread from any other thread, which should be okay in this context. – Julian Oct 23 '22 at 11:08
  • 2
    Yes, it's possible. Personally I am not a fan of the style of programming that involves `InvokeRequired`/`Invoke`. I prefer to keep the non-UI work separated from the UI work. – Theodor Zoulias Oct 23 '22 at 11:37
  • Helpful stuff, folks, thanks. Think one day I'm going to have to wrestle the lion and just pin down this whole async business. – stigzler Oct 23 '22 at 14:56