c#中同步代码到异步代码的转换

本文关键字:代码 转换 异步 同步 | 更新日期: 2023-09-27 17:49:24

我正在尝试使我的方法变成可以异步调用的东西。

通常从AddQueue方法中,我只会调用WorkingSession类中的ListOfJobsInQueue方法,获得它的结果并完成它。

使用什么信息我可以找到关于异步编程在这里,我已经完成了下面的代码,但它似乎是卡住在CurrentPageCode属性调用。

它甚至没有到达MessageBox。显示"处理完成"+ queueResult。 line.

有没有人可以帮助我,告诉我我错在哪里?

    //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)
    //***

c#中同步代码到异步代码的转换

死锁问题实际上是这个方法:

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

async代码中应避免调用Task.WaitTask<T>.Result。我在我的博客上完整地解释了死锁,但总结的版本是await将捕获上下文(在本例中是UI上下文)并尝试在该上下文(在本例中是UI线程)上恢复其async方法。对于某些上下文(例如UI上下文),如果你阻塞了该上下文中的线程(例如,在UI线程中调用Task<T>.Result),那么async方法无法在该上下文中恢复,从而导致死锁。

要解决这个问题,请使用async:

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

这段代码也是不理想的,尽管是以更微妙的方式:

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

通过在Task.Run中包装整个方法的逻辑,你真正做的是编写一个"假异步"方法。它有一个异步签名,但逻辑只是在后台线程上同步工作。

最好将任何Task.Run使用尽可能地推到UI层;不要让它出现在任何可重用的库方法中。让你的api告诉你真相:为同步工作提供同步签名。

我能做的最简单的

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