简体   繁体   中英

WPF MVVM ViewModel multithreading and async when requesting data from the backend

I have a WPF app that is just a GUI for selecting records from a database based on some criteria. It uses EF Core 5 LINQ syntax but it's, basically, a SELECT with a WHERE clause, under the hood, with a subsequent processing of the returned records.

Currently my setup is the following:

Two projects - WPF and a Console App. The WPF is everything frontend, while the console is the database access.
The WPF window has textboxes and a button. The textboxes are used as the filters for the LINQ .Where() while the button has an ICommand bound to it. The command calls a method from the console app that takes the textboxes contents as arguments, selects records from the database and processes the results before returning them to the WPF to be displayed.

I want to delegate the work to other threads/async as best as I can. I'm thinking using async for the database access and multithreading for the processing. However I am not that proficient with async, so I get the problem of "If I make the database access methods async they return a task and I don't know how to tell the ThreadPool to execute that task on another thread, not the UI one."

This is my pseudocode:

public class ConsoleApp
{
    public List<TUser> GetDaData(string userName, string department)
    {
        var users = GetUsers(userName, department);
        return ProcessUsers(users);
    }

    private List<TUser> ProcessUsers(List<TUser> users)
    {
        // do work
    }

    private List<TUser> GetUsers(string userName, string department)
    {
        dbContext.TUsers.Where(user =>
            (user.Name == userName || userName == null)
            && (user.Department == department || department == null)).ToList();
    }
}


class WpfStuff
{
    public UserName, Department; // pseudo properties with backing fields, databound to the TextBoxes content properties.
    public List<TUser> Users; // pseudo property with backing field, databound to a DataGrid's "ItemSource" property.

    public WpfStuff
    {
        // this is the command databound to the button.
        GetUsersCommand = new RelayCommand(OnGetUsers, CanGetUsers);
    }

    void OnGetUsers()
    {
        Users = ConsoleApp.GetDaData(UserName, Department);
    }

    bool CanGetUsers() => true;
}

So, as it is shown, this will run on the UI thread. I want to make it so that the "GetUsers" method would get the list async and EF Core 5 has a .ToListAsync() method but that requires I make the method async and make it return a Task and I am not sure how to wait on the result on that task, without blocking AND tell the application to Task.Factory.StartNew(() => ConsoleApp.GetDaData) at the same time.

Any help is appreciated!

I don't know if this is what you want, but I'll tell you

public class ConsoleApp
{
    // ----- 
    // add 'async'
    // -----
    public async Task<List<TUser>> GetDaData(string userName, string department)
    {
        var users = GetUsers(userName, department);
        return ProcessUsers(users);
    }

    private List<TUser> ProcessUsers(List<TUser> users)
    {
        // do work
    }

    private List<TUser> GetUsers(string userName, string department)
    {
        dbContext.TUsers.Where(user =>
            (user.Name == userName || userName == null)
            && (user.Department == department || department == null)).ToList();
    }
}


class WpfStuff
{
    public UserName, Department; // pseudo properties with backing fields, databound to the TextBoxes content properties.
    public List<TUser> Users; // pseudo property with backing field, databound to a DataGrid's "ItemSource" property.

    public WpfStuff
    {
        // this is the command databound to the button.
        GetUsersCommand = new RelayCommand(OnGetUsers, CanGetUsers);
    }

    // i'm not sure, this need async....
    void OnGetUsers()
    {
        Users = await Task.Run(ConsoleApp.GetDaData(UserName, Department));
    }

    bool CanGetUsers() => true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM