在我的应用程序中有三个线程,如:
private Thread _analysisThread;
private Thread _head2HeadThread;
private Thread _formThread;
并以下列方式启动每个线程:
if (_analysisThread == null || !_analysisThread.IsAlive)
{
_analysisThread = new Thread(() => { Analysis.Logic(match); });
_analysisThread.Start();
}
我有一个ListView,用户可以在其中选择一个项目,然后重新开始该线程,但我希望防止这种情况导致每个线程内的方法都很重,所以需要时间来完成它们。 / p>
到现在为止,我想禁用ListView
选项,所以我做了:
<ListView IsEnabled="{Binding IsMatchListEnabled}">
private bool _isMatchListEnabled = true;
public bool IsMatchListEnabled
{
get { return _isMatchListEnabled; }
set
{
_isMatchListEnabled = value;
OnPropertyChanged();
}
}
在新线程开始之前我做:IsMatchListEnabled = false;
但是我需要做的是检查所有线程是否都已完成然后执行:IsMatchListEnabled = true;
,实际上如果我之后启用了ListView
所有线程,我得到ListView
甚至已启用&#39;因为Thread
代码是异步的,Thread
之外的代码是同步的,所以实际上这个属性是无用的。
我试图避免这种情况是创建一个像这样的无限循环:
while (true)
{
if (!_analysisThread.IsAlive && !_head2HeadThread.IsAlive && !_formThread.IsAlive)
{
IsMatchListEnabled = true;
break;
}
}
在所有线程执行之后放置此循环,但是您可以想象,这将冻结应用程序。 任何解决方案?
答案 0 :(得分:2)
所有评论都是正确的 - 最好使用Tasks
。只是回答OP的问题。
您可以使用ManualResetEvent
来同步线程,通过线程数包含一系列事件,并在所有线程完成时更改IsMatchListEnabled
一个额外线程。
public static void SomeThreadAction(object id)
{
var ev = new ManualResetEvent(false);
events[id] = ev; // store the event somewhere
Thread.Sleep(2000 * (int)id); // do your work
ev.Set(); // set the event signaled
}
然后,在其他地方我们需要初始化等待例程。
// we need tokens to be able to cancel waiting
var cts = new CancellationTokenSource();
var ct = cts.Token;
Task.Factory.StartNew(() =>
{
bool completed = false;
while (!ct.IsCancellationRequested && !completed)
{
// will check if our routine is cancelled each second
completed =
WaitHandle.WaitAll(
events.Values.Cast<ManualResetEvent>().ToArray(),
TimeSpan.FromSeconds(1));
}
if (completed) // if not completed, then somebody cancelled our routine
; // change your variable here
});
可以找到完整的示例并查看here。
答案 1 :(得分:1)
我建议使用Microsoft的Reactive Framework。它比任务更强大,代码比使用线程简单得多。
假设您有3个长期运行的操作:
Action huey = () => { Console.WriteLine("Huey Start"); Thread.Sleep(5000); Console.WriteLine("Huey Done"); };
Action dewey = () => { Console.WriteLine("Dewey Start"); Thread.Sleep(5000); Console.WriteLine("Dewey Done"); };
Action louie = () => { Console.WriteLine("Louie Start"); Thread.Sleep(5000); Console.WriteLine("Louie Done"); };
现在您可以编写以下简单查询:
IObservable<Unit> query =
from a in new [] { huey, dewey, louie }.ToObservable()
from u in Observable.Start(() => a())
select u;
你这样运行:
Stopwatch sw = Stopwatch.StartNew();
IDisposable subscription = query.Subscribe(u => { }, () =>
{
Console.WriteLine("All Done in {0} seconds.", sw.Elapsed.TotalSeconds);
});
我得到的结果是:
Huey Start Dewey Start Louie Start Huey Done Louie Done Dewey Done All Done in 5.0259197 seconds.
三个5秒的操作在5.03秒内完成。全部并行。
如果您想提前停止计算,请致电subscription.Dispose()
。
NuGet“System.Reactive”获取位。