如何将方法转换为异步/等待 C#

Posted

技术标签:

【中文标题】如何将方法转换为异步/等待 C#【英文标题】:How to convert method to async / await C# 【发布时间】:2016-01-18 11:42:09 【问题描述】:

您好,我的 C# Web 服务中有以下方法:

[WebMethod(EnableSession = true)]
        //[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
        public object[] GetChartData()
        

            System.Threading.Thread.Sleep(5000);

            string graphData = "";

            List<GoogleChartData> data = new List<GoogleChartData>();

            using (DBContext context = new DBContext ())
            
                data = context.Campaings.AsNoTracking().Take(10).Select(c => new GoogleChartData
                
                    Year = 2015,
                    USA = 1,
                    Mexico = 2,
                    Canada = 3
                ).ToList();
            

            var chartData = new object[data.Count + 1];
            chartData[0] = new object[]
                "Year",
                "USA",
                "Mexico",
                "Canada"
            ;

            Random random = new Random();

            int j = 0;
            foreach (var i in data)
            


                j++;
                chartData[j] = new object[]  i.Year.ToString(), random.Next(0, 1000), random.Next(0, 1000), random.Next(0, 1000) ;
            
            return  chartData;   

        

我在多次从同一个应用程序调用时遇到问题,所以我想让它异步。我是 Async / Await 的新手。

有什么线索吗?

【问题讨论】:

我在弄清楚你有什么问题时遇到了问题......你可能想先为你正在使用的框架寻找一些 async/await 示例(看起来像 WebForms)。 鉴于 Web 开发的性质,async/await 不太可能在这里为您提供帮助。也许您应该更具体地了解您遇到的问题? 为什么你的程序里面有 5 秒的睡眠时间?当您多次调用该方法时,您究竟遇到了什么“问题”。编辑:你的代码有很多没有意义的东西,你做了.Select(c =&gt;,但你从来没有在选择中使用c,你为什么要进行数据库调用? @VAAA Web 服务请求由单独的后台线程处理,您不需要需要使用async/await 来使它们异步。问题是什么,显示问题的代码在哪里?您如何调用服务? . 【参考方案1】:

我不太清楚你想要什么,但如果你想在你的函数中使用Await/Async,这是你的线索(假设你正在使用Entity Framework 6):

public async Task<object[]> GetChartData()

    List<GoogleChartData> data;
    using (DBContext context = new DBContext ())
    
        data = await context.Campaings.AsNoTracking().Take(10).Select(c => new GoogleChartData
        
            Year = 2015,
            USA = 1,
            Mexico = 2,
            Canada = 3
        ).ToListAsync(); // Use ToListAsync()
    

    // The rest are the same

编辑!!!

正如VAAA在评论中所说,ToListAsync()在他的情况下是不可用的,所以我尝试寻找另一种解决方案。

感谢Scott Chamberlain在评论中的想法,解决方案是:使用来自调用者的Task.Run(() =&gt; GetChartData())

对于那些打算在GetChartData() 中使用Task.Run() 的人:我们应该 make asynchronous wrappers for synchronous code。

【讨论】:

假设我没有 ToListAsync() ,如何将其转换为异步 @VAAA 您需要从您使用的任何库中找到任何方法的异步版本。如果没有异步方法,您可能会通过不使其异步获得更好的性能。 @AnhTriet 在函数中执行Task.Run“使其异步”几乎从来都不是一个好主意,更好的选择是让调用者执行Task.Run(() =&gt; GetChartData()),并拥有任务.Run 由希望它在后台线程中运行的调用者进行。你应该not to make asynchronous wrappers for synchronous code。 好的,我完全同意你的看法。我会更新我的答案:) 谢谢。 Web 服务请求已经在单独的线程中运行。使用async/await 不会使方法异步,它已经 是。 async/await 在这种情况下意味着 request 线程可以在等待数据库响应时被释放。 other 线程 已经处理了其他请求【参考方案2】:

看看 Creating an async webservice method

[WemMethod]
public async Task<List<ErrorLog>> GetAllErrorLogs()

List<ErrorLog> errorLogs = new List<ErrorLog>();
await System.Threading.Tasks.Task.Run(() => 
    errorLogs = ErrorLogRepository.GetAllErrorLogs();
)
if (errorLogs == null)
    return new List<ErrorLog>();
return errorLogs;

【讨论】:

做你所做的除了通过产生一个新线程来增加服务器上的开销之外,什么也做不了。你完成的唯一一件事就是让他的程序变慢了。如果您在 IIS 项目中使用Task.Run,您可能做错了什么。

以上是关于如何将方法转换为异步/等待 C#的主要内容,如果未能解决你的问题,请参考以下文章

将图像异步转换为 Base64 的 C# 简单应用程序

C#如何将T的动作转换为T的任务的等待函数

将 jquery .getJSON 转换为 ajax 异步等待 YouTube API

不使用异步等待的异步等待

C# 中的 C++ std::async 与异步/等待

异步在 C# 中如何工作?