Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关于线程和异步方法在C中是否真正异步的混淆#_C#_.net_Asynchronous - Fatal编程技术网

C# 关于线程和异步方法在C中是否真正异步的混淆#

C# 关于线程和异步方法在C中是否真正异步的混淆#,c#,.net,asynchronous,C#,.net,Asynchronous,我正在阅读async/await,当任务时。Yield可能有用,我在那篇文章中遇到了一个关于以下内容的问题: 当您使用async/await时,无法保证您可以使用该方法 在等待时调用fooancy()实际上将异步运行。 内部实现可以使用完整的 同步路径 这对我来说有点不清楚,可能是因为我脑子里对异步的定义不一致 在我看来,因为我主要做UI开发,所以异步代码不是在UI线程上运行的代码,而是在其他线程上运行的代码。我猜在我引用的文本中,如果方法在任何线程上阻塞(例如,即使它是线程池线程),那么它就不

我正在阅读async/await,当
任务时。Yield
可能有用,我在那篇文章中遇到了一个关于以下内容的问题:

当您使用async/await时,无法保证您可以使用该方法 在等待时调用
fooancy()
实际上将异步运行。 内部实现可以使用完整的 同步路径

这对我来说有点不清楚,可能是因为我脑子里对异步的定义不一致

在我看来,因为我主要做UI开发,所以异步代码不是在UI线程上运行的代码,而是在其他线程上运行的代码。我猜在我引用的文本中,如果方法在任何线程上阻塞(例如,即使它是线程池线程),那么它就不是真正的异步方法

问题:

如果我有一个CPU受限的长时间运行的任务(假设它正在做大量的数学运算),那么异步运行该任务一定会阻塞一些线程,对吗?事实上,有些东西需要做数学运算。如果我等待它,那么一些线程将被阻塞


什么是真正的异步方法的示例?它们实际上是如何工作的?这些操作是否仅限于利用某些硬件功能的I/O操作,因此不会阻塞任何线程?

这个主题相当广泛,可能会出现一些讨论。然而,在C#中使用
async
await
被认为是异步编程。然而,异步是如何工作的是一个完全不同的讨论。在.NET4.5之前,没有async和Wait关键字,开发人员必须直接针对y(TPL)进行开发。在那里,开发人员可以完全控制何时以及如何创建新任务,甚至线程。然而,这有一个缺点,因为不是这个主题的真正专家,应用程序可能会因为线程之间的竞争条件等而遭受严重的性能问题和bug

从.NET4.5开始,引入了async和await关键字,以及异步编程的新方法。async和await关键字不会导致创建其他线程。异步方法不需要多线程,因为异步方法不在自己的线程上运行。该方法在当前同步上下文上运行,仅当该方法处于活动状态时才使用线程上的时间。您可以使用
Task.Run
将CPU绑定的工作移动到后台线程,但是后台线程对只等待结果可用的进程没有帮助

在几乎所有情况下,基于异步的异步编程方法都比现有方法更可取。特别是,对于IO绑定的操作,这种方法比BackgroundWorker更好,因为代码更简单,并且您不必担心竞争条件。您可以阅读有关此主题的更多信息

我不认为自己是一个黑腰带,一些经验丰富的开发人员可能会提出一些进一步的讨论,但作为一个原则,我希望我能回答你的问题。p> 当您使用async/await时,不能保证您在wait foosync()时调用的方法将实际异步运行。内部实现可以使用完全同步的路径自由返回

这对我来说有点不清楚,可能是因为 在我的脑海里,我没有排队

这仅仅意味着调用异步方法时有两种情况

首先,在将任务返回给您时,操作已经完成——这将是一条同步路径。第二个问题是操作仍在进行中——这是异步路径

考虑这段代码,它应该显示这两条路径。如果密钥在缓存中,则同步返回。否则,将启动一个异步操作,调用数据库:

Task<T> GetCachedDataAsync(string key)
{
    if(cache.TryGetvalue(key, out T value))
    {
        return Task.FromResult(value); // synchronous: no awaits here.
    }
    
    // start a fully async op.
    return GetDataImpl();
    
    async Task<T> GetDataImpl()
    {
        value = await database.GetValueAsync(key);
        cache[key] = value;
        return value;
    }
}

下面是异步代码,它显示了async/await如何允许代码阻塞并释放对另一个流的控制,然后恢复控制,但不需要线程

public static async Task<string> Foo()
{
    Console.WriteLine("In Foo");
    await Task.Yield();
    Console.WriteLine("I'm Back");
    return "Foo";
}


static void Main(string[] args)
{
    var t = new Task(async () =>
    {
        Console.WriteLine("Start");
        var f = Foo();
        Console.WriteLine("After Foo");        
        var r = await f;
        Console.WriteLine(r);
    });
    t.RunSynchronously();
    Console.ReadLine();
}
公共静态异步任务Foo()
{
Console.WriteLine(“在Foo中”);
等待任务;
Console.WriteLine(“我回来了”);
返回“Foo”;
}
静态void Main(字符串[]参数)
{
var t=新任务(异步()=>
{
控制台写入线(“开始”);
var f=Foo();
Console.WriteLine(“Foo之后”);
var r=等待f;
控制台写入线(r);
});
t、 同步运行();
Console.ReadLine();
}

因此,在需要结果时释放控制和重新同步是async/await的关键(这在线程处理中非常有效)

注意:在生成此代码时未阻止任何线程:)

我认为有时这种混乱可能来自“任务”,它并不意味着在自己的线程上运行某些东西。它只意味着一件事要做,async/await允许将任务分解为多个阶段,并将这些不同的阶段协调成一个流

这有点像烹饪,你按照食谱做。你需要做所有的准备工作,然后再组装菜来做饭。所以你打开烤箱,开始切割东西,磨碎东西等等。然后你等待烤箱的温度,等待准备工作。你可以用一种似乎合乎逻辑的方式(tasks/async/await)在任务之间切换,但你可以让别人帮你磨碎奶酪,同时切碎胡萝卜(线程),以便更快地完成任务

这对我来说有点不清楚,可能是因为我脑子里对异步的定义不一致

谢谢你要求澄清

在我看来,因为我主要做UI开发,所以异步代码不是在UI线程上运行的代码,而是在其他线程上运行的代码

这种信念是普遍的,但却是错误的。异步代码不需要在任何第二个线程上运行

想象你正在做早餐。你在烤面包机里放些吐司
public static async Task<string> Foo()
{
    Console.WriteLine("In Foo");
    await Task.Yield();
    Console.WriteLine("I'm Back");
    return "Foo";
}


static void Main(string[] args)
{
    var t = new Task(async () =>
    {
        Console.WriteLine("Start");
        var f = Foo();
        Console.WriteLine("After Foo");        
        var r = await f;
        Console.WriteLine(r);
    });
    t.RunSynchronously();
    Console.ReadLine();
}
var result = await Task.Run(() => MySynchronousCpuBoundCode());
var a = await A();
await B(a);
public async Task<int> A()
{
  Thread.Sleep(1000);

  return 42;
}
public async Task<int> A()
{
  await Task.Delay(1000);

  return 42;
}
var responseTask = GetAsync("http://www.google.com");

// Do some CPU intensive task
ComputeAllTheFuzz();

response = await responseTask;
private static async Task CallFooAsync()
{
    await FooAsync();
}

private static Task FooAsync()
{
    return Task.CompletedTask;
}

private static void Main()
{
    CallFooAsync().Wait();
}
    private async void button1_Click(object sender, EventArgs e)
    {
        await WorkAsync(5000);
        textBox1.Text = @"DONE";
    }

    private async Task WorkAsync(int milliseconds)
    {
        Thread.Sleep(milliseconds);
    }
    private async void button1_Click(object sender, EventArgs e)
    {
        await Task.Run(() => Work(5000));
        textBox1.Text = @"DONE";
    }

    private void Work(int milliseconds)
    {
        Thread.Sleep(milliseconds);
    }