问题
I'm trying to run multi-threaded tasks under main task using following code but not working expectedly.
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
using (var socketClient = new SocketClient()) {
Task.Factory.StartNew(() => {
Console.WriteLine("Starting child task...");
if (cancellationToken.IsCancellationRequested) {
Console.WriteLine("Task cancellation requested");
throw new OperationCanceledException(cancellationToken);
}
List<string> pairsList = db.GetPairsList(); //loads from db and it's dynamic
try {
// loop through each pair
Parallel.ForEach(pairsList, pair => {
Console.WriteLine("Item {0} has {1} characters", pair, pair.Length);
SubscribeToStream(socketClient);//I'm subscribing to some socket streams
});
} catch (OperationCanceledException ex) {
Console.WriteLine(ex.Message);
}
}, cancellationToken);
}
Subscribe method is as follows:
private void SubscribeToStream(string pair, SocketClient socketClient) {
var subscribePair = socketClient.SubscribeToPair(pair, data => {
//here socket stream returns callback each second for each pair
Application.Current.Dispatcher.Invoke(() => {
//if perfect match found then Remove pair from the list
if(a == b) {
db.removePair(pair);
}
//after removing refresh new pairs list to see if new pair added or removed from the main list from db..
}
//after match, we need to unsubscribe from the current pair
socketClient.UnsubscribeFromPair(subscribePair.Data);
//IT CALLS SAME PAIR AGAIN EVEN AFTER UNSUBSCRIBING FROM SOCKET STREAM
}
}
I want to run a main task which holds child tasks separately. Start button will start main thread and Stop button will stop all threads safely along with main thread.
Each child thread subscribed to some socket streams which runs for each pairs. If matched data found then I'm removing that pair from the pairs list but thread continues due to stream subscription or thread might not been cancelled successfully. However, I'm able to cancel the main thread but I want to cancel specific thread/task not the main task and allow the main task continues along with existing or newly added pairs.
How can we safely achieve this scenario?
回答1:
For every thread/task you want to cancel, you need to forward it the cancellationToken and check for that repeatedly. So you need to make sure your inner Task (in the Parallel.ForEach loop) also repeatedly checks the cancellationToken and aborts if it is triggered.
Hint: It is good practice to always keep a reference to created tasks, to be able to check whether it has really ended. So keep a reference to the return value of Factory.StartNew() and use it later to check that the task has really ended.
来源:https://stackoverflow.com/questions/49217722/cancel-specific-child-thread-or-task-after-unsubscribing-socket-stream