MikeDub
MikeDub

Reputation: 5283

Converting Synchronous code to Asynchronous code in C#

I am trying to make a method of mine into something that can be called asynchronously.

Normally from the AddQueue Method, I would just call the ListOfJobsInQueue methods in the WorkingSession class, get its result and be done with it.

Using what info I could find regarding Async programming on here, I have done up the below code, but it seems to be getting stuck on the CurrentPageCode property call.

It does not even get to the MessageBox.Show("Processing complete with " + queueResult.Count + " rows"); line.

Could someone please assist and show me where I'm going wrong?

    //Primary Class

    public void AddQueue()
    {
        MessageBox.Show(GetJobsFromQueueAsync().Result.Count().ToString());
    }

    async Task<List<string>> GetJobsFromQueueAsync()
    {
        Task<List<string>> getJobsTask = WorkingSession.GetlistOfJobsAsync();
        List<string> queueResult = await getJobsTask;
        MessageBox.Show("Processing complete with " + queueResult.Count + " rows");
        return queueResult;
    }

    //***

    //WorkingSession Class

    public Task<List<string>> GetlistOfJobsAsync()
    {
        return Task.Run<List<string>>(() =>
        {
            return ListOfJobsInQueue();
        });
    }

    public List<string> ListOfJobsInQueue()
    {
        if (CurrentPageCode == "CS1")
        {
            List<string> actionList = new List<string>();
            short pageNum = PageCurrent;
            short pageMax = PageMax;

            for (short atPage = pageNum; atPage <= pageMax; atPage++)
            {
                //Scan each job on the current queue page
                for (int lineNum = 5; lineNum < 18; lineNum++)
                {
                    string reference = GetJobText(new Coordinate { row = lineNum });
                    actionList.Add(reference);
                }
                //Once finished with this job page, goto the next
                SendCMDKey(Mnemonic.F8);
            }
            return actionList;
        }
        else
        {
            return null;
        }
    }

    //Other method / property signatures (for reference)

    public string CurrentPageCode;
    public bool SendCMDKey(Mnemonic command)
    public string GetJobText(Coordinate coordinate)

    //***

Upvotes: 0

Views: 1843

Answers (2)

alhpe
alhpe

Reputation: 1514

The simplest that I can

   public async Task<int> GetWorkFlowStageAsync(string tracker,CancellationToken? token = null)
        {
            return await Task.FromResult(0);
        }

Upvotes: 0

Stephen Cleary
Stephen Cleary

Reputation: 456322

The deadlock problem is actually this method:

public void AddQueue()
{
    MessageBox.Show(GetJobsFromQueueAsync().Result.Count().ToString());
}

Calling Task.Wait or Task<T>.Result should be avoided in async code. I explain the deadlock in full on my blog, but the summary version is that await will capture a context (in this case, the UI context) and attempt to resume its async method on that context (in this case, on the UI thread). With some contexts (e.g., the UI context), if you block a thread in that context (e.g., calling Task<T>.Result on the UI thread), then the async method cannot resume on that context, causing a deadlock.

To fix it, use async all the way:

public async Task AddQueueAsync()
{
    var jobs = await GetJobsFromQueueAsync();
    MessageBox.Show(jobs.Count().ToString());
}

This code is also not ideal, though in a much more subtle way:

public Task<List<string>> GetlistOfJobsAsync()
{
    return Task.Run<List<string>>(() =>
    {
        return ListOfJobsInQueue();
    });
}

By wrapping an entire method's logic in Task.Run, what you're really doing is writing a "fake asynchronous" method. It's got an asynchronous signature but the logic is just synchronous work on a background thread.

It's best to push any Task.Run use as far towards the UI layer as possible; keep it out of any reusable library methods. Make your APIs tell the truth: have synchronous signatures for synchronous work. I have a blog series that goes into detail.

Upvotes: 3

Related Questions