gpt4 book ai didi

c# - 从同步方法调用异步方法

转载 作者:可可西里 更新时间:2023-11-01 07:56:30 25 4
gpt4 key购买 nike

我正在尝试从同步方法运行异步方法。但是我不能await async 方法,因为我处于同步方法中。我一定不了解 TPL,因为这是我第一次使用它。

private void GetAllData()
{
GetData1()
GetData2()
GetData3()
}

每个方法都需要前一个方法完成,因为第一个方法的数据用于第二个。

但是,在每个方法中,我想启动多个 Task 操作以加快性能。然后我想等他们全部完成。

GetData1 看起来像这样

    internal static void GetData1 ()
{
const int CONCURRENCY_LEVEL = 15;
List<Task<Data>> dataTasks = new List<Task<Data>>();
for (int item = 0; item < TotalItems; item++)
{
dataTasks.Add(MyAyncMethod(State[item]));
}
int taskIndex = 0;
//Schedule tasks to concurency level (or all)
List<Task<Data>> runningTasks = new List<Task<Data>>();
while (taskIndex < CONCURRENCY_LEVEL && taskIndex < dataTasks.Count)
{
runningTasks.Add(dataTasks[taskIndex]);
taskIndex++;
}

//Start tasks and wait for them to finish
while (runningTasks.Count > 0)
{
Task<Data> dataTask = await Task.WhenAny(runningTasks);
runningTasks.Remove(dataTask);
myData = await dataTask;


//Schedule next concurrent task
if (taskIndex < dataTasks.Count)
{
runningTasks.Add(dataTasks[taskIndex]);
taskIndex++;
}
}
Task.WaitAll(dataTasks.ToArray()); //This probably isn't necessary
}

我在这里使用 await 但出现错误

The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'

但是,如果我使用 async 修饰符,这将是一个异步操作。因此,如果我对 GetData1 的调用不使用 await 运算符,则在第一次等待时将无法控制转到 GetData2,这是我要避免的吗?是否可以将 GetData1 保留为调用异步方法的同步方法?我是否错误地设计了异步方法?如您所见,我很困惑。

这可能是 How to call asynchronous method from synchronous method in C#? 的副本但是,我不确定如何应用那里提供的解决方案,因为我正在启动多个任务,想要 WaitAny,对该任务做更多处理,然后等待所有任务完成将控制权交还给调用者。

更新

这是我根据以下答案采用的解决方案:

    private static List<T> RetrievePageTaskScheduler<T>(
List<T> items,
List<WebPageState> state,
Func<WebPageState, Task<List<T>>> func)
{
int taskIndex = 0;

// Schedule tasks to concurency level (or all)
List<Task<List<T>>> runningTasks = new List<Task<List<T>>>();
while (taskIndex < CONCURRENCY_LEVEL_PER_PROCESSOR * Environment.ProcessorCount
&& taskIndex < state.Count)
{
runningTasks.Add(func(state[taskIndex]));
taskIndex++;
}

// Start tasks and wait for them to finish
while (runningTasks.Count > 0)
{
Task<List<T>> task = Task.WhenAny(runningTasks).Result;
runningTasks.Remove(task);

try
{
items.AddRange(task.Result);
}
catch (AggregateException ex)
{
/* Throwing this exception means that if one task fails
* don't process any more of them */

// https://stackoverflow.com/questions/8853693/pattern-for-implementing-sync-methods-in-terms-of-non-parallel-task-translating
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(
ex.Flatten().InnerExceptions.First()).Throw();
}

// Schedule next concurrent task
if (taskIndex < state.Count)
{
runningTasks.Add(func(state[taskIndex]));
taskIndex++;
}
}

return items;
}

最佳答案

Task<TResult>.Result (或 Task.Wait() ,当没有结果时)类似于 await ,而是一个同步操作。你应该改变 GetData1()使用这个。这是要更改的部分:

Task<Data> dataTask = Task.WhenAny(runningTasks).Result;
runningTasks.Remove(dataTask);
myData = gameTask.Result;

关于c# - 从同步方法调用异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19010337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com