Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.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#_Async Await_Task_Abstract - Fatal编程技术网

C# 等待抽象异步任务

C# 等待抽象异步任务,c#,async-await,task,abstract,C#,Async Await,Task,Abstract,我对async/await用法非常陌生。我试图抽象异步,并在UI中有条件地等待。我有一个抽象基类: public abstract class Base { public abstract bool IsRunning { get; } public abstract Task<bool> Run(); } 希望这是清楚的。我是否可以执行上述操作,特别是在if块内有条件地等待?理想情况下,对于Run方法,我想让Base类只返回bool而不是Task,并且只让Deri

我对
async/await
用法非常陌生。我试图抽象异步,并在UI中有条件地等待。我有一个抽象基类:

public abstract class Base
{
    public abstract bool IsRunning { get; }
    public abstract Task<bool> Run();
}
希望这是清楚的。我是否可以执行上述操作,特别是在if块内有条件地等待?理想情况下,对于
Run
方法,我想让
Base
类只返回
bool
而不是
Task
,并且只让
Derived2
类重写来返回
任务
,但我不清楚如何做。也许我应该在
Derived2
Run
方法中返回
task.Result
?如果有更好的方法,包括抽象或任何其他更正,请让我知道。谢谢你的建议

编辑#1

Derived1
中同步实现的
Run
方法表单已在下面的响应中阐明。但是,我不允许更改
DoSomething
方法的签名,因此考虑到
Derived2
(异步实现)中我的
Run
方法现在看起来如下(感谢@Stripling的注释):


我不知道您的同步版本是如何同步的,您仍然使用
任务。Run(
),这是我所期望的

internal class Derived1 : Base
{
    private readonly Base baseCase;
    private Task<bool> task;
    public Derived1(Base baseCase)
    {
        this.baseCase = baseCase;
    }
    public override bool IsRunning
    {
        get { return false; }    

    }

    public override Task<bool> Run()
    { 
        bool ok = DoSomething(); 
        return Task.FromResult(ok);
    }
}
异步版本将异步运行,同步版本将同步运行

您的“异步版本”也不是真正的异步版本,请参阅以了解执行该方法的正确方法

我是否可以执行上述操作,特别是在if块内有条件地等待

可以,但不必。如果你做得对,以阻塞方式专门调用同步任务没有什么好处:一般来说,你可以等待返回的任务,如果它代表一个同步任务,
wait
将以非常小的代价同步解析头顶

当我说“如果你做对了事情”,以下是正确的方式:

// synchronous
public override Task<bool> Run()
{
    var result = DoSomething();
    return Task.FromResult(result);
}


// asynchronous
public override async Task<bool> Run()
{
    var result = await DoSomethingAsync();
    return result;
}
//同步
公共覆盖任务运行()
{
var结果=剂量测量();
返回Task.FromResult(结果);
}
//异步的
公共重写异步任务运行()
{
var result=wait DoSomethingAsync();
返回结果;
}
wait
ing上面第一个示例的结果不会执行任何线程切换或类似操作。
wait
ing第二个示例的结果可能会执行,具体取决于
DoSomethingAsync()的实现
。没有特别需要抽象层:您可以随时检查
任务是否已完成,并且
等待
等待一个已完成的任务将始终立即返回值。

用于返回包含同步计算结果的任务,然后等待

bool ok = DoSomething();
return Task.FromResult(ok);
作为旁注,我不会将同步代码放在一个通常是异步的(或在其他类/位置是同步的)方法中,反之亦然。对于同步和异步实现,我会使用不同的接口/基类

interface IRunnable
{
    bool IsRunning;
    bool Run();
}

interface IRunnableAsync
{
    bool IsRunning;
    Task<bool> RunAsync();
}
接口IRunnable
{
布尔正在运行;
bool-Run();
}
接口同步
{
布尔正在运行;
任务RunAsync();
}
然后在UI中,我想等待异步任务(如果用户在运行时配置中指定了异步任务)

首先,我不得不说这是一个非常糟糕的主意。有些东西应该是可配置的,有些不应该。操作的异步性不应该是可配置的。这是一个可怕的设计,我要做的第一件事就是对荒谬的“需求”进行严格的回击就像这样。它与是否抛出异常的可配置标志具有相同的意义

这就是说,这是可以做到的。这很痛苦,很难维持,而且在一天结束时完全没有用。但是,嘿,我想你会为此得到报酬,所以一切都很好,嗯

如果出于政治原因(绝对没有有效的技术原因),您必须执行此操作,那么我建议您使用。仅阻塞(
Result
)的一个问题是,如果
Run
使用
wait
(for),则无法执行此操作

布尔参数hack只是添加一个布尔参数,指示该方法是否需要同步完成

public abstract class Base
{
  public abstract Task<bool> RunAsync(bool sync);
}
这叫做:

private async void OnRun(object sender, EventArgs args)
{
  foreach (var case in Cases)
  {
    Base baseCaseRunner = GetCaseRunner(case);
    try
    {
      bool sync = !something_holds;
      bool ok = await baseCaseRunner.RunAsync(sync);
    }
    catch (Exception e)
    {
      LogError(...);
    }
  }
}

请注意,它总是可以用
await
调用,但是如果
sync
true
,那么
OnRun
实际上将是同步的。这是由于“wait fast path”(如我的异步介绍博客文章中所述).

你能用高级术语解释一下你想做什么吗?@YacoubMassad:让我试试。我正在尝试创建一个抽象类和一个派生类,它们异步实现一些方法,而另一个派生类则不异步实现,然后在UI中根据我所处的情况有条件地等待。看看这个:WRT edit#2:你是We’我们试图对一个只希望由特定线程访问的对象执行某些操作。这种情况经常发生在具有指定UI线程的应用程序中。如果不知道是哪行代码导致了错误,就很难确切地知道如何帮助您。@StriplingWarrior:我正在尝试进一步调试,但到目前为止,在Ed中的用法是否正确它#1看起来还好吗?谢谢,很高兴知道我可以在任何任务上使用wait。那么我甚至不需要if-condition。但是如果对于您示例中的异步运行方法,我无法像您那样在DoSomethingAsync上使用wait(即,我不想使用async关键字而只返回任务),该怎么办由于我的任务是使用lambda函数定义的。我想我接下来的问题是,如果我需要使用lambda函数来实例化任务,如何使用async/await关键字?我找到了上面问题的答案。请参阅我的编辑1。我将对此进行测试并稍后返回
private async void OnRun(object sender, EventArgs args)
{
    foreach (var case in Cases)
    {
        Base baseCaseRunner = GetCaseRunner(case);
        try
        {
            bool ok = true;
            ok = await baseCaseRunner.Run();
        }
        catch (Exception e)
        {
            LogError(...);
        }
    }
}
// synchronous
public override Task<bool> Run()
{
    var result = DoSomething();
    return Task.FromResult(result);
}


// asynchronous
public override async Task<bool> Run()
{
    var result = await DoSomethingAsync();
    return result;
}
bool ok = DoSomething();
return Task.FromResult(ok);
interface IRunnable
{
    bool IsRunning;
    bool Run();
}

interface IRunnableAsync
{
    bool IsRunning;
    Task<bool> RunAsync();
}
public abstract class Base
{
  public abstract Task<bool> RunAsync(bool sync);
}
internal class Derived1 : Base
{
  public override async Task<bool> RunAsync(bool sync)
  {
    IsRunning = true;
    try
    {
      if (sync)
        return DoSomething();
      return await Task.Run(() => DoSomething());
    }
    finally
    {
      IsRunning = false;
    }
  }
}
private async void OnRun(object sender, EventArgs args)
{
  foreach (var case in Cases)
  {
    Base baseCaseRunner = GetCaseRunner(case);
    try
    {
      bool sync = !something_holds;
      bool ok = await baseCaseRunner.RunAsync(sync);
    }
    catch (Exception e)
    {
      LogError(...);
    }
  }
}