Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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#_Multithreading_Asynchronous - Fatal编程技术网

C# 在没有第二个线程帮助的情况下异步执行代码?

C# 在没有第二个线程帮助的情况下异步执行代码?,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,好的,首先,我不需要实现任何东西。我只需要知道答案,因为有经验的人告诉我,异步执行不一定要涉及新线程,因为线程是一些复杂的结构,这让我很困惑,我不能同意 现在让我们假设,我有两个方法-Execute()和ExecuteAsync()执行()正在主线程上运行。我想从Execute()中调用ExecuteAsync(),我不在乎它何时完成执行,但当它完成执行时,我想使用它的返回值。这是一个典型的异步执行示例,对吗 我知道我可以使用BackgroundWorker或IAsyncResult(Deleg

好的,首先,我不需要实现任何东西。我只需要知道答案,因为有经验的人告诉我,异步执行不一定要涉及新线程,因为线程是一些复杂的结构,这让我很困惑,我不能同意

现在让我们假设,我有两个方法-
Execute()
ExecuteAsync()
<代码>执行()正在主线程上运行。我想从
Execute()
中调用
ExecuteAsync()
,我不在乎它何时完成执行,但当它完成执行时,我想使用它的返回值。这是一个典型的异步执行示例,对吗

我知道我可以使用
BackgroundWorker
IAsyncResult
Delegate.BeginInvoke()
)来实现这一点,但在后台它们会生成一个辅助CLR线程/线程池线程

那么,在没有第二个线程帮助的情况下异步执行方法
ExecuteAsync()
是否可能呢

编辑:我认为这一编辑将进一步澄清这一情况。调用
ExecuteAsync()
不是
Execute()
要执行的唯一(或最后)任务
Execute()
应该继续它自己的任务,而不必关心
ExecuteAsync()
方法的执行

那么,在没有第二个线程帮助的情况下异步执行ExecuteAsync()方法是否可能呢

有些方法可以在不使用新线程的情况下异步运行。例如,这可以通过使用来完成。框架的大多数新异步方法尽可能地添加到.NET4.5AsyncIO中,而不是线程中

这就是为什么最好不要假设异步==新线程。虽然异步可以使用线程实现,但并不总是以这种方式实现。最好将异步操作看作(希望)不会阻塞的操作,并且在将来的某个时候会完成。

是使用单个物理线程实现多个逻辑线程的常用方法。较旧的操作系统使用此概念和其他相关概念来实现


在这种情况下,您可能也对这个主题感兴趣,并且有一个很好的博客系列-,。

以下是一个使用异步且从不使用多个线程的程序示例:

public class Foo
{
    private int _value;
    private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    public int Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            var oldTCS = tcs;
            tcs = new TaskCompletionSource<bool>();
            oldTCS.SetResult(true);
        }
    }


    public Task ValueChanged()
    {
        return tcs.Task;
    }
}

private static void Main(string[] args)
{
    Foo foo = new Foo();
    foo.ValueChanged()
        .ContinueWith(t =>
        {
            Console.WriteLine(foo.Value);
        }, TaskContinuationOptions.ExecuteSynchronously);

    foo.Value = 5;
}
现在我们可以用一种形式来表示:

private async void button1_Click(object sender, EventArgs args)
{
    Form2 otherForm = new Form2();
    otherForm.Show();

    await otherForm.WhenClosed();

    //take some data from that form and display it on this form:
    textBox1.Text = otherForm.Name;
}
创建和显示另一个表单从不涉及创建新线程。此表单和新表单都完全使用要创建和修改的一个UI线程

关闭时从
返回的
任务
的创建根本不需要创建新线程

等待
任务
时,不会创建新线程。当前方法结束,UI线程返回处理消息。在某个时刻,同一个UI线程将执行某些操作,导致关闭第二个表单。这将导致任务继续运行,从而返回到我们的按钮点击处理程序,在那里我们设置文本框的文本


所有这些都是通过UI线程完成的,没有创建其他线程。然而,我们只是“等待”(而不是实际等待)一个长时间运行的操作完成(用户将一些信息放入第二个表单,然后关闭它),而不阻塞UI线程,从而保持主表单的响应性。

@I4V仍然(通常)使用线程池线程,不过,你为什么不看看c#和.NET4.5的新特性呢?使用async和await就是您要讨论的。另外,看看这个。async/await只是改变了您使用异步操作的方式——它并没有改变它们(必然)的实现方式。@NerotheZero不完全如此。只有在默认情况下。创建任务的方法有很多种,有些使用线程池,有些使用新(非池)线程,有些两者都不使用。我有点困惑于“创建
任务不需要新线程”
…”。好吧,在.NET 4.0之前,任务本身在引擎盖下使用
线程池
线程。@NerotheZero直到.NET 4.0
任务
都不存在,所以显然它不可能是引擎盖下的任何东西。4.0版之后(即,对于整个
任务的历史记录而言,
)有些任务会创建一个全新的线程,有些任务涉及线程池项目的运行,有些任务两者都不涉及。我举了两个例子,这两个例子都是最后一个“两者都不是”的例子。从
TaskCompletionSource
创建的
Task
不会产生新线程或线程池线程,并且从大多数IO调用创建的任务也不会使用其他线程。这是使任务真正强大的部分原因。对不起,我指的是4.0版的
Task
类,是在TPL@NerotheZeroTPL之前没有任何版本的
任务
。引入TPL的全部意义在于它引入了
Task
。再次抱歉,我的意思正是
Task
类,首先在.NET4.0中引入。可能是我的“直到.NET4.0”让你感到困惑。无论如何,我不知道使用
任务
会导致
没有新线程
的情况。谢谢你的解释。这真的帮了大忙。@NerotheZero否-通常,CPU受限的异步代码将使用另一个线程。您可以通过协程,或者通过Servy的示例等机制来完成,尽管在这种情况下异步操作正在运行时,您没有运行其他工作……我看到链接的内容涉及I/O操作和较低级别的中断信号,AFAIK也用于I/O操作。你建议我应该考虑在处理器上执行一个I/O操作的代码吗?
private async void button1_Click(object sender, EventArgs args)
{
    Form2 otherForm = new Form2();
    otherForm.Show();

    await otherForm.WhenClosed();

    //take some data from that form and display it on this form:
    textBox1.Text = otherForm.Name;
}