gpt4 book ai didi

C# 任务返回输出

转载 作者:行者123 更新时间:2023-11-30 17:43:17 25 4
gpt4 key购买 nike

我已经阅读了很多关于如何为任务返回值的内容,但我似乎无法让它在我的代码上工作并且仍然产生 System.Threading.ThreadAbortException .

尝试使用 Task.WaitAll尽管这可能会阻止 UI 但无济于事。

public DataTable GetResult(SomeVariable someVariable) {
// this do not work
//var task = Task<DataTable>.Factory.StartNew(() =>
var task = Task.Factory.StartNew<DataTable>(() =>
{
DataTable matchedData = new DataTable();
matchedData = DoTask(someVariable);
return matchedData;
}, TaskCreationOptions.LongRunning);
try
{
var allTasks = new Task[] { task };
Task.WaitAll(allTasks);
return task.Result as DataTable;
}
catch (ArgumentException)
{
throw;
}
catch (Exception)
{
// Always get the exception here: "A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll"
throw;
}
}

尝试使用 ContinueWhenAll但还是一样。

public DataTable GetResultV2(SomeVariable someVariable)
{
queue = new Queue<Task>();
DataTable matchedData = new DataTable();
var task = Task.Factory.StartNew(() =>
{
matchedData = DoTask(someVariable);
return matchedData;
}, TaskCreationOptions.LongRunning);
queue.Enqueue(task);
try
{
var done = Task.Factory.ContinueWhenAll(queue.ToArray(), completed =>
{
return matchedData;
});
return done.Result as DataTable;
}
catch (ArgumentException)
{
throw;
}
catch (Exception)
{
// Always get the exception here: "A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll"
throw;
}
}

DoTask只是一种检查和查询数据库的方法。

private DataTable DoTask(SomeVariable someVariable)
{
DataTable matchedData = new DataTable();
// long database process/query
// populate and return matchedData
return matchedData;
}

编辑:引用如何/为什么使用它。



foreach (DataRow row in data.Rows)
{
string columnName = Convert.ToString(row["columnName"]);
string ProjectName = Convert.ToString(row["ProjectName"]);
string dbase_group = Convert.ToString(row["dbase_group"]);
string dbase_data = Convert.ToString(row["dbase_data"]);
var task = Task.Factory.StartNew(() =>
{
SomeVariable someVariable = new SomeVariable();
someVariable.DbName = dbase_group;
someVariable.columnName = columnName;
someVariable.ProjectName = ProjectName;
someVariable.TblName = dbase_data;
using (SearchProject search = new SearchProject())
{
DataTable result = new DataTable();
result = search.GetResult(SomeVariable);
}
});
queue.Enqueue(task);
}
Task.Factory.ContinueWhenAll(queue.ToArray(), ant =>
{
Console.WriteLine("Done with all tasks");
});

最佳答案

我认为您是时候开始使用 async/await 了。这将使您的生活更加轻松。

您希望在代码中的某处启动多个任务并等待所有任务完成而不阻塞您的用户界面。在您的示例中,这是 GetResult。

您希望 GetResult 返回一个 DataTable 对象。如果您想使用异步等待,您可以声明函数 GetResult 并返回一个任务,如下所示:

public async Task<DataTable> GetResultAsync(SomeVariable someVariable) {...}

It is quite common to name your async functions with the word async at the end

在此函数中,您可以启动任务,在这些任务运行时做其他事情,并等待任务完成。这种等待称为“await”。

您只能等待任务或任务对象,因此您等待返回任务的函数。

Task.WaitAll 不返回 Task,而是返回 void。所以你不能等待 Task.Waitall。

更好的方法是等待 Task.WhenAll。该函数返回一个任务,因此您可以等待它。

public async Task<DataTable> GetResultAsync(SomeVariable someVariable)
{
var task = Task.Run( () =>
{
DataTable matchedData = new DataTable();
matchedData = DoTask(someVariable);
return matchedData;
}
}

If you want you can still use Task.Factory.StartNew, see MSDN for discussions why they nowadays prefer Task.Run

这个函数会给你一个结果。如果要调用 if,则必须使调用函数也异步并让它返回 Task 或 Task。它的调用者也应该是异步的,直到你到达事件处理程序。这是唯一可能返回 void 的:

private async void OnButton1_clicke(object Sender, ...)
{
try
{
await ProcessAllInputsAsync(...)
}
catch (ArgumentException exc)
{
ProcessArgumentException(...)
}
catch (Exception exc)
{
ProcessOtherException(...)
}
}

// first example: no parallel processing:
private async Task ProcessAllInputsAsync(...)
{
foreach (SomeVariable someVariable in GetSomeVariables(...))
{
DataTable dataTable = await GetResultAsync(...);
ProcessDataTable(dataTable);
}
}

// or do parallel processing: start several tasks and wait until all ready:
private async Task ProcessAllInputsAsync(...)
{
List<Task<DataTable>> tasks = new List<Task<DataTable>>();
foreach (SomeVariable someVariable in GetSomeVariables(...))
{
tasks.Add(GetResultAsync(someVariable);
}
// all tasks are started, await for all to finish:
await Task.WhenAll(tasks.ToArray());
// REMEMBER: you can only await for a Task or Task<T>
// Task.WhenAll returns a Task, so you can await for it
// Task.WaitAll returns void, so you can't await for it.

// now that all tasks are finished, get the results:
// Each Task<TResult> has the result in property Task.Result
// The result of a Task<TResult> is a TResult:
IEnumerable<TResult> fetchedDataTables = tasks.Select(task => task.Result);

// you can process it here if you want or do other things with it:
foreach (DataTabe fetchedDataTable in fetchedDataTables)
{
ProcessFetchedDataTable(fetchedDataTable);
}
}

See that you got rid of all ContinueWith etc stuff. It is replace by await, followed by the next statement where the result of the task is available in Task.Result.

Be aware: if you do a Task.WhenAll, and one of the tasks you are waiting for throws an exception, you get an AggregateException where all exceptions thrown by all tasks are grouped in property InnerExceptions. So if you want you can catch the AggregateException and foreach all innerexceptions to see which task threw which exceptions.

关于C# 任务返回输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31174309/

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