C# 异步/等待,而另一个方法执行此操作

C# 异步/等待,而另一个方法执行此操作,c#,async-await,C#,Async Await,我想实现一个流程,在我的类中调用异步方法时,它们将注册到调度程序列表并等待。然后另一个线程运行并执行调度器列表中的方法,当每个操作完成时,等待将完成,我将返回计算的值 以下是我目前的代码: private List<Func<ClassA, ClassB, ResponseBase>> _actionsDict; public ExecutingScheduler() { _actionsDict = new List<Func<ClassA, Cla

我想实现一个流程,在我的类中调用异步方法时,它们将注册到调度程序列表并等待。然后另一个线程运行并执行调度器列表中的方法,当每个操作完成时,等待将完成,我将返回计算的值

以下是我目前的代码:

private List<Func<ClassA, ClassB, ResponseBase>> _actionsDict;
public ExecutingScheduler()
{
    _actionsDict = new List<Func<ClassA, ClassB, ResponseBase>>();
    Task.Factory.StartNew(ExecuteNextTask);
}

private void ExecuteNextTask()
{
    while (_actionsDict.Count > 0)
    {
        // Get first while removing it
        var next = _actionsDict[0];
        _actionsDict.RemoveAt(0);

        // Next line has an error now, how do I call it with the original params as I added it to the list
        next();

        Task.Delay(2000);
    }
}

public async Task<ResponseBase> StartStreamAsync(ClassA classA, ClassB classB)
{
    _actionsDict.Add((unit, guid) => StartStream(classA, classB));

    // I don't want the first each time, I want to await the same instance as I added
    var response = await Task.Run(() => _actionsDict[0](classA, classB)); 
    return response;
}

public async Task<ResponseBase> PrepareStreamAsync(ClassA classA, ClassB classB)
{
    _actionsDict.Add((unit, guid) => PrepareStream(classA, classB));

    // I don't want the first each time, I want to await the same instance as I added
    var response = await Task.Run(() => _actionsDict[0](classA, classB)); 
    return response;
}
private List\u actionsDict;
公共执行调度器()
{
_actionsDict=新列表();
Task.Factory.StartNew(ExecuteNextTask);
}
私有void ExecuteNextTask()
{
而(_actionsDict.Count>0)
{
//移除时先获取
var next=_actionsDict[0];
_行动信息通信移除(0);
//下一行现在有一个错误,当我将它添加到列表中时,如何使用原始参数调用它
next();
任务.延迟(2000年);
}
}
公共异步任务StartStreamAsync(ClassA ClassA,ClassB ClassB)
{
_actionsDict.Add((单位,guid)=>StartStream(classA,classB));
//我不希望每次都是第一次,我希望等待我添加的相同实例
var response=wait Task.Run(()=>_actionsDict[0](classA,classB));
返回响应;
}
公共异步任务PrepareStreamAsync(ClassA ClassA,ClassB ClassB)
{
_actionsDict.Add((单位,guid)=>PrepareStream(类别A,类别B));
//我不希望每次都是第一次,我希望等待我添加的相同实例
var response=wait Task.Run(()=>_actionsDict[0](classA,classB));
返回响应;
}
所以有两个问题: 1) 如何正确地添加到操作列表中,以便以后可以使用其参数逐个调用列表中的函数

2) 如何正确地将executer方法的返回值传递给原始请求的调用者


请随意提出不同的方法

我不太明白你的问题。但是我假设您需要一个包含两个
async
方法的类,它们将按照
actionDict
中的顺序进行操作

无论如何,代码如下:(新版本)

List_actionsDict=newlist();
定时器_定时器=新定时器(1000);
公共执行调度器()
{
_计时器运行时间+=(s,e)=>{
而(_actionsDict.Count>0){
var a=_actionsDict[0];
_行动信息通信移除(0);
a、 Start();
a、 等待();
}
};
_timer.Start();
}
公共任务StartStreamAsync(ClassA ClassA,ClassB ClassB)
{
返回QueueResponse(()=>StartStream(classA,classB));
}
公共任务PrepareStreamAsync(ClassA ClassA,ClassB ClassB)
{
返回QueueResponse(()=>PrepareStream(classA,classB));
}
公共任务队列响应(Func操作)
{
var t=新任务(操作);
_行动D.增加(t);
返回Task.Run(()=>t.Result);
}
(已编辑) 您可以将任务添加到集合,而不是向actions集合添加函数

//Better use thread-safe ConcurrentQueue
private ConcurrentQueue<Task<ResponseBase>> _actions;

public ExecutingScheduler()
{
    _actions = new ConcurrentQueue<Task<ResponseBase>>();
    Task.Factory.StartNew(ExecuteNextTask);
}

private void ExecuteNextTask()
{
    while (true)
    {
        // Get first while removing it
        Task<ResponseBase> next;
        var containsElement = _actions.TryDequeue(out next);
        if (containsElement)
        {
            next.Start();
            next.Wait();
        }
        Task.Delay(2000);
    }
}

public async Task<ResponseBase> StartStreamAsync(ClassA classA, ClassB classB)
{
    var task = new Task<ResponseBase>(() => StartStream(classA, classB));

    //Add task to queue
    _actions.Enqueue(task);

    var result = await task;

    return result;
}

public async Task<ResponseBase> PrepareStreamAsync(ClassA classA, ClassB classB)
{
    var task = new Task<ResponseBase>(() => PrepareStream(classA, classB));

    //Add task to queue
    _actions.Enqueue(task);

    var result = await task;
    return result;
}
//更好地使用线程安全的ConcurrentQueue
私有ConcurrentQueue动作;
公共执行调度器()
{
_actions=新的ConcurrentQueue();
Task.Factory.StartNew(ExecuteNextTask);
}
私有void ExecuteNextTask()
{
while(true)
{
//移除时先获取
下一个任务;
var containseElement=\u actions.TryDequeue(下一步输出);
if(容器组件)
{
next.Start();
下一步。等待();
}
任务.延迟(2000年);
}
}
公共异步任务StartStreamAsync(ClassA ClassA,ClassB ClassB)
{
var任务=新任务(()=>StartStream(classA,classB));
//将任务添加到队列
_行动。排队(任务);
var结果=等待任务;
返回结果;
}
公共异步任务PrepareStreamAsync(ClassA ClassA,ClassB ClassB)
{
var任务=新任务(()=>PrepareStream(classA,classB));
//将任务添加到队列
_行动。排队(任务);
var结果=等待任务;
返回结果;
}

看起来您正在尝试重新实现任务并行库。特别是
TaskScheduler
Task.whalll

试试这个

var queries = new [] 
              { 
                  new { ClassA =..., ClassB = ...},
                  new { ClassA =..., ClassB = ...},
                  new { ClassA =..., ClassB = ...},
              };
var tasks = queries.Select(item => Task.Run(() => PrepareStream(item.ClassA, item.ClassB);
var results = await Task.WhenAll(tasks);
然而,对于像
PrepareStream
这样的名称,我怀疑您确实不想使用线程


线程只应在CPU受限或具有特殊(UI)线程(这是CPU受限的一种特殊情况)时使用。

如何解释一下您的代码?它与OP的代码有什么不同/正确之处?它不会运行。而且肯定不能异步工作。@CliveDM我认为它将异步运行,但它只会死锁,仅此而已#NeverUseTaskResult@Aron在他最初的帖子中,他没有等待任务运行,因此任务将同步运行。当类被构造时,
executeexttask
方法(现在已修复)将只运行一次,此时
\u actionsDict.Count>0
将为false,并且整个方法将立即返回,而不调用该方法,所有任务将在列表中排队而不执行。因此,
task.Result
将永远无法获得,这将导致整个线程死机。@NikitaIlin是的,它似乎正在运行。一个问题,一旦整个队列用完了,这个<代码>(真)会消耗大量的CPU时间(我的意思是全部),考虑使用“<代码>定时器< /代码>。你查看了吗?”AlxD:你要求一个非常复杂的解决方案,这就叫我问:为什么你需要这个?你想解决的实际问题是什么?@StephenCleary我想他想把一堆伪
任务排成一列,然后异步运行,然后等待
完成。到底是什么
返回任务。运行(()=>Task.Result)
?!您的意思是
返回任务。ConfigureAwait(false)
?@Aron当然不是,用户可以调用
await StartStreamAsync
意味着方法应该返回
var queries = new [] 
              { 
                  new { ClassA =..., ClassB = ...},
                  new { ClassA =..., ClassB = ...},
                  new { ClassA =..., ClassB = ...},
              };
var tasks = queries.Select(item => Task.Run(() => PrepareStream(item.ClassA, item.ClassB);
var results = await Task.WhenAll(tasks);