我正在编写.NET 4.0 C#软件,我需要并行执行一些代码来加快工作。
我有一个Job
课程,可能包含多个Job
课程作为孩子
每当Job
开始运行时,它都会调用Children.AsParallel.ForAll(ch => ch.Run());
我在一个单独的线程上开始工作,但是我必须使用Thread.Abort()
然后Thread.Join(5000)
来终止它,以确保它已经终止。
无论如何,似乎在.AsParallel()
下运行的乔布斯继续正常工作......
以下是代码:
class Job
{
public string Name;
public List<Job> Children = new List<Job>();
public void Run()
{
for(int i = 0; i < 5; i++)
{
int tid = Thread.CurrentThread.ManagedThreadId;
var msg = "JOB " + Name + " " + tid;
Debug.WriteLine(msg);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Children.AsParallel().ForAll(j => j.Run());
}
}
[TestMethod]
public void TestMultiThread()
{
var root = new Job();
root.Name = "A";
root.Children = new List<Job>()
{
new Job() { Name = "B" },
new Job() { Name = "C" },
};
var t = new Thread(() =>
{
try
{
root.Run();
}
catch(ThreadAbortException tae)
{
}
});
t.Start();
Thread.Sleep(TimeSpan.FromSeconds(7));
Debug.WriteLine("THREAD.ABORT");
t.Abort();
t.Join(TimeSpan.FromSeconds(5));
Thread.Sleep(TimeSpan.FromSeconds(5));
}
这是输出:
JOB A 14
JOB A 14
JOB A 14
JOB A 14
JOB A 14
JOB B 9
JOB C 15
JOB B 9
JOB C 15
THREAD.ABORT
JOB B 9
JOB C 15
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in Test.dll
in System.Threading.ThreadHelper.ThreadStart_Context(Object state)
in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
in System.Threading.ThreadHelper.ThreadStart()</StackTrace><ExceptionString>System.Threading.ThreadAbortException: Thread interrotto.
in Test.Tests.OtherTests.&lt;&gt;c__DisplayClass14.&lt;TestMultiThread&gt;b__13() in Tests.cs:riga 280
in System.Threading.ThreadHelper.ThreadStart_Context(Object state)
in System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
in System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
An exception of type 'System.Threading.ThreadAbortException' occurred in Test.dll but was not handled in user code
The thread '<No Name>' (0x14d0) has exited with code 0 (0x0).
JOB B 9
JOB C 15
JOB B 9
JOB C 15
The thread '<No Name>' (0x152c) has exited with code 0 (0x0).
有什么我错过的吗?
答案 0 :(得分:1)
作为提及的评论者,您可以使用CancellationTokenSource并取消令牌。我在这里所做的就是使用Token.ThrowIfCancellationRequested来破解所有任务。
您修改过的代码 :
void Main()
{
TestMultiThread();
}
// Define other methods and classes here
class Job
{
public string Name;
public List<Job> Children = new List<Job>();
public void Run(CancellationTokenSource tokenSource)
{
for(int i = 0; i < 5; i++)
{
int tid = Thread.CurrentThread.ManagedThreadId;
var msg = "JOB " + Name + " " + tid +" cnt "+ i;
Debug.WriteLine(msg);
Thread.Sleep(TimeSpan.FromSeconds(1));
tokenSource.Token.ThrowIfCancellationRequested();
}
Children.AsParallel()
.ForAll(j => j.Run(tokenSource));
}
}
public void TestMultiThread()
{
var root = new Job();
root.Name = "A";
root.Children = new List<Job>()
{
new Job() { Name = "B" },
new Job() { Name = "C" },
};
CancellationTokenSource cts = new CancellationTokenSource();
var t = System.Threading
.Tasks
.Task
.Factory.StartNew(()=> root.Run(cts),cts.Token);
Thread.Sleep(TimeSpan.FromSeconds(7));
Debug.WriteLine("Task Cancel requested");
cts.Cancel();
Debug.WriteLine("Task Canceled");
try
{
t.Wait(TimeSpan.FromSeconds(5));
}
catch(Exception ex)
{
//Linqpad famous Dump method
ex.Dump();
}
Thread.Sleep(TimeSpan.FromSeconds(5));
}
答案 1 :(得分:0)
不要使用Thread.Abort而是使用标志,这样您就可以控制何时完全退出作业。看看TPL文档。
https://msdn.microsoft.com/en-us/library/dd537607%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396