Reputation: 361
I have function that received List
of files and do work in separate threads:
private static CancellationTokenSource _tokenSource;
private static int _filesInProcess;
private static int _filesFinished;
private IEnumerable<Tuple<int, string>> _indexedSource;
public static int FilesInProcess
{
get { return _filesInProcess; }
set { _filesInProcess = value; }
}
public static int FilesFinished
{
get { return _filesFinished; }
set { _filesFinished = value; }
}
public void DoWork(int parallelThreads)
{
_filesInProcess = 0;
_filesFinished = 0;
_tokenSource = new CancellationTokenSource();
var token = _tokenSource.Token;
Task.Factory.StartNew(() =>
{
try
{
Parallel.ForEach(_indexedSource,
new ParallelOptions
{
MaxDegreeOfParallelism = parallelThreads //limit number of parallel threads
},
file =>
{
if (token.IsCancellationRequested)
return;
//do work...
});
}
catch (Exception)
{ }
}, _tokenSource.Token).ContinueWith(
t =>
{
//finish...
}
, TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread
);
}
As you can see i have 2 variables that indicate how many files already start and how many finished (_filesInProcess and _filesFinished)
My questions:
Upvotes: 2
Views: 70
Reputation: 35905
1 Do I need to set these variables to be accessed from different threads or this is OK ?
Yes you do. Couple of things. You should add a volatile
keyword to the declarations of the counters, like
private static volatile int _filesInProcess;
This ensures that all the reads actually read the current value, in contrast to reads of a cashed value. If you want to modify and read the counters, you should consider using the Interlocked
class, for example Interlocker.Increment
2 After the function finished and all my files finished to play and i want to start a new one, there is option to do from Task class or simple while will do the work for me ?
Not sure about this one, wild guess (it's not clear what you need). You can use task continuations, like you did (last block of code). As alternative a Task.Factory.StartNew
returns a task, which you could save to a local variable and start it as you please (say on a button click). You may need to update the code slightly as Task.Factory.StartNew
will kick the task immediately, while you may only want to create a task and run it on an event.
Based you your comment you can do something like (coded in notepad)
private Task _task; // have a local task variable
// move your work here, effectively what you have in Task.Factory.StartNew(...)
public void SetupWork()
{
task = new Task (/*your work here*/);
// see, I don't start this task here
// ...
}
// Call this when you need to start/restart work
public void RunWork()
{
task.Run();
}
Upvotes: 2