将同步方法更改为异步方法

2024-04-02

我在谷歌上搜索了很多并阅读了不同的菜鸟教程,但我认为我不明白正确的做法是什么。基本上,现有的同步代码会在服务器启动并运行时执行某些操作。有时(很少见),服务器需要更长的时间才能启动,因此我想将其包装在一些重试逻辑中。我构建了一个完全愚蠢的控制台应用程序来尝试了解 async 和 wait 是如何工作的,并想出了这个:

    private static int counter = 0;

    static void Main(string[] args)
    {
        DoIt();
        Console.ReadLine();
    }

    static bool LongTask()
    {
        if (counter == 2)
        {
            Console.WriteLine("finally true");
            Thread.Sleep(1000);
            return true;
        }
        counter++;
        Console.WriteLine("false");
        Thread.Sleep(1000);
        return false;
    }

    public static Task<bool> WrapperLongTask()
    {
        Console.WriteLine("wrapper called");
        return Task.Run(() => LongTask());            
    }

    public static async Task DoIt()
    {
        Console.WriteLine("hi");
        var result = await WrapperLongTask();
        while (result != true)
        {
            result = await WrapperLongTask();
            Console.WriteLine("inside while loop");
        }
        Console.WriteLine($"outside while loop {result}");
        Console.WriteLine("bye");
    }

我的 LongTask 函数代表我当前的函数,该函数通常第一次就可以工作。然后调用这个方法可以吗

Task.Run(() => LongTask())

假设这是“好的”,那么我基本上会在我当前方法的实际代码中创建它DoWork().

Task DoWorkAsync(....) {
     return Task.Run(() => DoWork()
}

基本上只是将其包装在 Task.Run 中,将返回类型更改为 Task。然后当我稍后调用这个方法时,我会做类似的事情

var x = await DoWorkAsync;
// do more stuff with x

这样我应该将以前的同步方法转换为异步吗?

Edit

DoWork 的伪代码(字符串目录,CancellationToken 令牌)

var files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
foreach (var file in files) {
    try {
       token.ThrowIfCancellationRequested();
       var fileName = Path.GetFileName(file);
       // check if file already exists on server, if not, upload it
    }
    catch (Exception exception) {
       // error handling
    }
}

简短的答案是“否”,您不能仅通过将操作包装为异步代码来将所有类型的同步代码转换为异步代码Task.Run并使方法返回Task.

通常,当所考虑的操作可能调用某些 IO 操作(文件系统读/写、网络或 Web 访问、数据库访问...等)时,异步代码才有意义。

例如,如果您有一个方法使用同步方法从文件中读取一些数据,例如FileStream.Read,然后对此类文件的内容进行一些 CPU 工作,然后您可以通过调用它来将您的方法转换为异步方法FileStream.ReadAsync相反,然后异步等待ReadAsync是通过使用来完成的await关键字,然后处理文件的内容(当然你必须更改方法以返回Task并成为async).

这种情况的好处是没有线程等待 IO 操作完成,而且线程的开销很大。

在服务器应用程序(例如 ASP.NET 网站)中,不需要线程等待 IO 操作完成的好处非常重要,因为在这些应用程序中您需要大量并发请求。但是,对于简单的应用程序,您可能一开始就不想使用异步代码。

您可以使用Task.Run如果您想在多个 CPU 核心上运行多个 CPU 密集型操作。

例如,如果您有 4 个 CPU 核心,则可以通过以下方式创建 4 个任务:Task.Run来处理一些数据。考虑前面的示例,在异步等待之后ReadAsync为了完成,你可以将读取的结果分成4部分(假设数据比较大),并通过创建4个任务Task.Run,每个将处理结果的一部分。然后,您可以使用异步等待 4 个任务完成Task.WhenAll.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将同步方法更改为异步方法 的相关文章

随机推荐

  • 四舍五入到 0.5

    我有一个结果 1 444444 我想将此结果舍入为 1 5 这是我使用的代码 a text String round 13000 9000 0 但这是四舍五入到 1 0 我需要四舍五入到 1 5 和这段代码 a text String ce
  • 属性。有什么有用的目的?

    Under System Runtime InteropServices the
  • Vim 显示:ImportError:没有名为 site 的模块。当我使用 Canopy1.1 时

    我在Windows Xp 32中安装了Canopy 1 1 express 并使用vim作为编辑器 当我打字时 python print hello 在vim命令行中显示 Importerror No module named site然后
  • Flutter Android SDK 版本 28 错误,但我使用的是 30

    当我创建一个新的 flutter 应用程序时 它启动 android sdk 版本 28 但我使用 android sdk 30 Flutter doctor 还显示了平台 android 30 build tools 30 0 2 当我尝
  • dll文件的描述

    您好 如何在 dll 文件中查找类的描述 在我的项目中 我在 imagealg dll 中使用 diff calss 告诉我如何找到那个的描述 plz 找到该类的描述的最佳位置是在文档中
  • Eclipse 自动建议并填写变量名称

    好的 所以我的问题是当我创建一个变量时 例如 Object o 当我输入 o 时 它会建议类似 object 的内容 没关系 但是当我按空格时 它会自动填充新名称 基本上我不想关闭自动完成 我只想禁用空格自动填充建议 甚至禁用变量命名建议也
  • 如何使用 C# 在 Excel 图表上添加多个系列

    我想添加一个如下图所示的图表 该图表有 3 个系列 黑色 红色 蓝色 以下是在图表上创建 一个 系列的代码块 Excel Workbook oWorkbook Excel Workbook oSheet Parent Excel Chart
  • 捕获最后一个 WM_SIZE

    当我调整窗口大小时 我想告诉程序的另一部分我的窗口大小已更改 我继续读下去MSDN http msdn microsoft com en us library ms632646 VS 85 aspx that WM 尺寸 留言WM SIZE
  • 将 less-plugin-glob 与 Webpack 结合使用

    我正在尝试将现有项目的构建系统从gulp to webpack 它当前有一个入口点 less 文件 可导入各种其他文件 如下所示 import bower components bootstrap less bootstrap less i
  • 即使在索引字段上,MongoDB 排序也非常慢

    今天我遇到了这个问题 我的 MongoDB 查询速度非常慢并且超时 我发布了这个问题 MongoDB 记录太多 https stackoverflow com questions 11701103 mongodb too many reco
  • iPhone 中的 jpg 图像和 2x 图像

    我正在开发 iphone 应用程序并定位iOS 4 0或稍后 我正在尝试将图像添加到 UIImageView 并且图像位于jpeg格式 这就是我到目前为止所做的 UIImageView bgImageView UIImageView all
  • Div 溢出滚动到底部:可能吗?

    如果我有一个div with overflow auto使其成为可滚动的div我加载它的信息会形成一个重要的滚动区域 有没有一种方法可以在我加载信息时 div显示底部结果 或者基本上滚动到底部 我见过 jQuery 解决方案 但这是在 HT
  • 如何让图片大小在滚动时平滑变化?

    我有带有大徽标的标题 我想在滚动超过 100px 后将其变小 这工作正常但不流畅 我怎样才能做到平滑 我的代码 function window scroll function if this scrollTop gt 100 header
  • AngularJS 登录表单与 ng-click 不起作用

    我在这个插件中写了一个基本的登录表单http plnkr co edit xQEN1ZNN5ZEw1CSwNw97 p preview http plnkr co edit xQEN1ZNN5ZEw1CSwNw97 p preview 单击
  • 如何在改造多部分请求中发送对象数组

    I want to send array objects with multipart data I tried many ways but it is not working My issue with the contributor p
  • 如何为Android Studio构建模板项目

    我使用 Android Studio 我必须创建许多始终包含三个模块的项目 应用程序 应用程序 图书馆 图书馆 壁纸 应用程序 我知道可以使用 ADT 来构建活动模板等 我找到了一些类似的教程this https android arsen
  • 在 C# 中使用 XSLT 将 RVML 转换为 SVG

    我有一个 C Web 应用程序 它使用以下命令生成 SVG 代码拉斐尔 JS http www raphaeljs com 然后我需要将其转换为 PNG 以实现用户之间的一般互操作性 请参阅我之前的问题在这里 https stackover
  • 如何从首选项屏幕返回到主要活动?

    我有一项主要活动和一项偏好活动 在我的第一个活动中 我调用菜单并通过调用startActivityForResult继续preferenceActivity case R id settings startActivityForResult
  • TCP 数据偶尔会以错误的顺序接收且不完整

    我用 Java 创建了 TCP 服务器应用程序 并用 C 创建了客户端应用程序 当我发送数据时 客户端有时会乱序接收数据 有时部分会完全丢失 基本上 我在服务器 java 中使用的代码如下 已删除 ServerSocket welcomeS
  • 将同步方法更改为异步方法

    我在谷歌上搜索了很多并阅读了不同的菜鸟教程 但我认为我不明白正确的做法是什么 基本上 现有的同步代码会在服务器启动并运行时执行某些操作 有时 很少见 服务器需要更长的时间才能启动 因此我想将其包装在一些重试逻辑中 我构建了一个完全愚蠢的控制