使用 Task.Factory. StartNew 传递方法参数

我有以下密码:

var task = Task.Factory.StartNew(CheckFiles, cancelCheckFile.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);


private void CheckFiles()
{
//Do stuff
}

现在我想修改 CheckFiles 以接受整数和 BlockingCollection 引用

private void CheckFiles(int InputID, BlockingCollection<string> BlockingDataCollection)
{
//Do stuff
}

我似乎不能像上面那样找到开始这项任务的方法。

你能帮忙吗?

谢谢

132147 次浏览

构造第一个参数作为 Action的实例,例如。

var inputID = 123;
var col = new BlockingDataCollection();
var task = Task.Factory.StartNew(
() => CheckFiles(inputID, col),
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);

最好的选择可能是使用一个 lambda 表达式来关闭要显示的变量。

但是,在这种情况下要小心,特别是在循环中调用这个函数时。(我提到这一点是因为您的变量是一个“ ID”,这在这种情况下很常见。)如果在错误的作用域中关闭变量,可能会出现 bug。有关详细信息,请参阅 埃里克 · 利伯特关于这个问题的帖子。这通常需要作出一个临时的:

foreach(int id in myIdsToCheck)
{
int tempId = id; // Make a temporary here!
Task.Factory.StartNew( () => CheckFiles(tempId, theBlockingCollection),
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}

另外,如果您的代码类似于上面的代码,那么您应该小心使用 LongRunning提示——使用默认的调度程序,这会导致每个任务获得自己的专用线程,而不是使用 ThreadPool。如果您正在创建许多任务,那么这可能会产生负面影响,因为您无法获得 ThreadPool 的优势。它通常适用于单个长时间运行的任务(因此得名) ,而不适用于集合中的某个项目,等等。

class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => MyMethod("param value"));
}


private static void MyMethod(string p)
{
Console.WriteLine(p);
}
}

对于传递单个整数,我同意 Reed Copsey 的答案。如果将来要传递更复杂的结构,我个人喜欢将所有变量作为匿名类型传递。它会看起来像这样:

foreach(int id in myIdsToCheck)
{
Task.Factory.StartNew( (Object obj) =>
{
var data = (dynamic)obj;
CheckFiles(data.id, theBlockingCollection,
cancelCheckFile.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}, new { id = id }); // Parameter value
}

你可以在我的 博客中学到更多

试试这个,

        var arg = new { i = 123, j = 456 };
var task = new TaskFactory().StartNew(new Func<dynamic, int>((argument) =>
{
dynamic x = argument.i * argument.j;
return x;
}), arg, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
task.Wait();
var result = task.Result;