Passing a method parameter using Task.Factory.Star

2019-01-16 15:33发布

I have the following code:

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

private void CheckFiles()
{
  //Do stuff
}

I now want to amend CheckFiles to accept and integer and a BlockingCollection reference

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

I can't seem to find a way to Start this task as I did above.

Can you help?

Thanks

4条回答
做自己的国王
2楼-- · 2019-01-16 16:04

The best option is probably to use a lambda expression that closes over the variables you want to display.

However, be careful in this case, especially if you're calling this in a loop. (I mention this since your variable is an "ID", and this is common in this situation.) If you close over the variable in the wrong scope, you can get a bug. For details, see Eric Lippert's post on the subject. This typically requires making a temporary:

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

Also, if your code is like the above, you should be careful with using the LongRunning hint - with the default scheduler, this causes each task to get its own dedicated thread instead of using the ThreadPool. If you're creating many tasks, this is likely to have a negative impact as you won't get the advantages of the ThreadPool. It's typically geared for a single, long running task (hence its name), not something that would be implemented to work on an item of a collection, etc.

查看更多
趁早两清
3楼-- · 2019-01-16 16:05

For passing a single integer I agree with Reed Copsey's answer. If in the future you are going to pass more complicated constucts I personally like to pass all my variables as an Anonymous Type. It will look something like this:

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
}

You can learn more about it in my blog

查看更多
叼着烟拽天下
4楼-- · 2019-01-16 16:12
class Program
{
    static void Main(string[] args)
    {
        Task.Factory.StartNew(() => MyMethod("param value"));
    }

    private static void MyMethod(string p)
    {
        Console.WriteLine(p);
    }
}
查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-01-16 16:19

Construct the first parameter as an instance of Action, e.g.

var inputID = 123;
var col = new BlockingDataCollection();
var task = Task.Factory.StartNew(
    () => CheckFiles(inputID, col),
    cancelCheckFile.Token,
    TaskCreationOptions.LongRunning,
    TaskScheduler.Default);
查看更多
登录 后发表回答