当前位置: 首页 > 知识库问答 >
问题:

与决定调用一个函数作为同步方法或任务有关的混乱

龙永福
2023-03-14

我正在学习asyncawait的基础知识,有时不清楚是否应该将方法构建为async

为了把问题弄清楚,我在下面写了两种方法来做同样的事情。在下面的两个示例中,mymethod()由Button1的click事件调用,并执行(推测)相同的操作:

第一道:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }
    
    private int MyMethod()
    {
        int x = 0;
    
        do
        {
            Thread.Sleep(100);
            x++;
    
        } while (x < 10);
    
        return x;
    }
    
    private async void button1_Click(object sender, EventArgs e)
    {
        Task<int> task = new Task<int>(MyMethod);
        task.Start();
    
        int MyNumber = await task;
        label1.Text = MyNumber.ToString();
    
    }
}

第二道:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
    }

    private async Task<int> MyMethodAsync()
    {
        int x = 0;

        do
        {
            await Task.Delay(100);
            x++;

        } while (x < 10);

        return x;
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        int MyNumber = await MyMethod();

        label1.Text = MyNumber.ToString();
    }
}    

我的困惑是,我该如何在这两种方法中选择?有没有推荐的方式?

作为一个初学者,我的倾向是只有在mymethod()中需要异步任务时,才将mymethod()转换为task。但是我无法得出结论,在其他情况下,将mymethod()作为任务来实现是否很好。

如果第一种方法适用于我们,那么第二种方法(将MyMethod转换为任务)是多余的吗,或者它甚至会产生不良后果?

共有2个答案

周玺
2023-03-14

区别在于第一个示例在后台线程上同步(并阻塞)执行myMethod(),而第二个示例在dispatcher线程上直接执行异步方法,而不阻塞它。

哪一个更好取决于方法的实际操作。通常,对于CPU密集型的工作,您更喜欢后台线程,对于IO相关的工作,例如处理文件或通过网络发送或接收字节时,您更喜欢异步方法。

另请注意,您应该使用task.run启动新任务,而不是使用task构造函数:

Task.Run(MyMethod);
万俟英锐
2023-03-14

这取决于你在做什么。

如果您主要是做与IO相关的工作,打开文件,等待网络等,那么第二个例子将是最合适的。这将在主线程上运行任何处理,因此您可以避免线程的开销,而线程的开销大多会被阻塞。

如果您正在进行处理密集型工作,那么第一个示例会更合适。在这种情况下,您不会有任何等待,但您可能仍然希望在后台线程上运行它,以避免阻塞UI。

 类似资料:
  • 问题内容: 如果一个同步方法调用另一个同步方法,那么线程安全吗? 问题答案: 是的,将方法标记为时,您实际上是在这样做: 当线程调用从method1进入method2时,它将确保它持有对的锁定,该锁定已经存在,然后可以通过。 当线程直接进入method1或method2时,它将阻塞直到获得锁(),然后进入。 正如詹姆斯·布莱克(James Black)在评论中指出的那样,您必须了解方法主体内部的操

  • 我想调用一个方法,从一个AsyncWork,从另一个类,我正在尝试这个 但我得到错误“。你能帮助我吗? 我的扩展活动:

  • 我有一个gradle任务,它调用一个脚本,并使用将命令行参数传递给脚本。 我将此任务称为gradle任务,具有以下任何选项 不过,我想看看我是否将taskAll拆分为多个任务,比如 我明白我将不得不复制taskAll来创建,,并删除其中的if条件和硬代码参数。 然而,我想知道是否有可能通过让只调用可执行文件的MainTask,然后让,,调用,并传递参数,和,来实现一个更简洁的实现。

  • 假设我们有两个类A、B和各自类的同步方法methodA、methodB。如果我们从synchronizedmethodA调用synchronized methodB,那么当methodB仍在执行时,线程是否仍对ObjectA保持锁定?

  • 这两种方法的主要区别是什么? 第一个使用

  • 同步调用异步方法最安全的方法是什么?