此问题已经在这里有了答案:
我正在一个WPF应用程序上,在其中我需要在START和STOP的简单方法内运行另一个进程(“ ABC”)(具有许多多线程和并行处理的长进程)。因此,当我单击“开始”时,需要连续运行过程“ ABC”,直到单击“停止”为止。在进程“ ABC”中,我不得不大量使用并行处理和多线程,因此,当运行进程“ ABC”的while循环时,UI屏幕将冻结。我需要它自由运行。循环运行得很好,但UI侧屏幕冻结。
我的期望是循环运行进程“ ABC”,直到它停止为止。现在,我正在使用后台工作程序运行其循环。它运行得很好,但是冻结了UI屏幕。因此,我想自由运行UI并进行处理而不会冻结。
我尝试下面的代码:
private async void BackgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
while (((App)Application.Current).IsStrategyRunning == true)
{
this.Dispatcher.Invoke(() =>
{
CriteriaSections.PhantomEntrance phantomEntrance = new CriteriaSections.PhantomEntrance();
phantomEntrance.startPhantomEntranceEvaluation();
});
}
}
但是很冻结。请你能给我建议吗?谢谢。
我正在使用以下代码调用BackgroundWorker1_DoWork:
private System.ComponentModel.BackgroundWorker BackgroundWorker1;
this.BackgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.BackgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.BackgroundWorker1_DoWork);
BackgroundWorker1.RunWorkerAsync();
在如下所示的startPhantomEntranceEvaluation过程中
public void startPhantomEntranceEvaluation()
{
try
{
if (((App)Application.Current).IsStrategyRunning == true)
{
PhantomEntrance phantomEntrance = new PhantomEntrance();
string script = parseCriteriaLines.parseCriteiraLines(phantomEntrance.txtScriptArea.Text);
if (script.Length > 2)
{
PhantomEntranceCriteria(script, triggerScript, rbTrue.IsChecked.Value);
}
}
}
catch (Exception ex)
{
ErrorLogHandling.printErrorLog(ex.ToString(), "PhantomEntrance->startPhantomEntranceEvaluation");
}
}
与之相关的进一步过程如下
public static void PhantomEntranceCriteria(string script, string triggerScript, bool triggerStatus)
{
double simpleGain = 0;
try
{
var builder = new StringBuilder();
var symbolList = StrategyDetailsAndList.symbolListFromFile;
var taskArray = new List<Task>();
var lstsymbolWithRanking = symbolListWithRanking(symbolList);
symbolListWithPosition = lstsymbolWithRanking.ToDictionary(x => x, y => true);
foreach (var symbol in symbolListWithPosition.Where(x => x.Value == true).ToList())
{
phantomEntranceResult = criteriaEvalution.Evaluate(script, false, new List<parseObj>(), ref builder, symbol.Key, "Phantom Entrance Criteria");
if (phantomEntranceResult.Values.FirstOrDefault() == true)
{
lock (_lock)
{
#region fake position
List<parseObj> tempList = phantomEntranceResult.SelectMany(q => q.Key).ToList();
var x = phantomEntranceResult.Keys;
var askprice = x.Select(q => q.Where(z => z.VariableName == "ASKPRICE()").Select(a => a.Value).FirstOrDefault()).FirstOrDefault();
var symbolName = x.Select(q => q.Select(z => z.symbolName).FirstOrDefault()).FirstOrDefault();
var currentAskPrice = PolygonSocket.SocketConnection.liveQuotesList.Where(q => q.sym == symbolName).Select(q => q.ap).LastOrDefault();
var currentBidPrice = PolygonSocket.SocketConnection.liveQuotesList.Where(q => q.sym == symbolName).Select(q => q.bp).LastOrDefault();
var currentTradePrice = PolygonSocket.SocketConnection.liveTradeList.Where(q => q.sym == symbolName).Select(q => q.p).LastOrDefault();
var currentTradeVolume = PolygonSocket.SocketConnection.liveTradeList.Where(q => q.sym == symbolName && q.t > (q.t - 1 * 60 * 1000)).Sum(q => q.s);
simpleGain = (((currentBidPrice / x.Select(q => q.Where(z => z.VariableName == "ASKPRICE()").Select(a => a.Value).FirstOrDefault()).FirstOrDefault()) - 1) * 5000);
var pctGain = (((currentBidPrice / x.Select(q => q.Where(z => z.VariableName == "ASKPRICE()").Select(a => a.Value).FirstOrDefault()).FirstOrDefault()) - 1) * 100);
var currentAskPrice_result = new parseObj("CURRANTASKPRICE", currentAskPrice, true, symbolName);
var currentBidPrice_result = new parseObj("CURRENTBIDPRICE", currentBidPrice, true, symbolName);
var currentTradePrice_result = new parseObj("CURRENTTRADEPRICE", currentTradePrice, true, symbolName);
var currentTradeVolume_result = new parseObj("CURRENTTRADEVOLUME", currentTradeVolume, true, symbolName);
var simpleGain_result = new parseObj("GAIN", simpleGain, true, symbolName);
var pctGain_result = new parseObj("PCTGAIN", pctGain, true, symbolName);
tempList.Add(currentBidPrice_result);
tempList.Add(currentAskPrice_result);
tempList.Add(currentTradePrice_result);
tempList.Add(currentTradeVolume_result);
tempList.Add(simpleGain_result);
tempList.Add(pctGain_result);
printFakePosition(tempList, symbolName, true, "Phantom Entrance Fake Position");
try
{
tempFakePositionList.Add(symbolName, tempList);
}
catch (Exception ex)
{
}
#endregion
}
parallelScripts.pExitWithEntrance(phantomEntranceResult);
}
else
{
//MessageBox.Show("Phantom Entrance become false");
}
}
}
catch (Exception ex)
{
ErrorLogHandling.printErrorLog(ex.ToString(), "PhantomEntrance->PhantomEntranceCriteria");
}
}
在上面的代码中,parallelScripts.pExitWithEntrance(phantomEntranceResult);
也包含很多类似上面的过程。在子区域中,附近有14个xaml页面,这些页面相互连接并相互依赖以执行操作。我在使用另一个dispatcher.invoke,后台工作程序和并行处理的地方。
正如注释中所指出的那样,您提供的代码表明您实际上正在UI线程上运行所有工作。
[当您调用RunWorkerAsync
时,BackgroundWorker
开始运行循环,然后循环使用startPhantomEntranceEvaluation
在UI线程上运行Dispatcher.Invoke
。因此,您要做的就是调用后台线程再次调用UI线程。没有任何实际工作在后台完成。
您需要重新编写代码,以便仅在/当您需要更新UI时才使用Dispatcher.Invoke
。另外,如果要坚持使用BackgroundWorker
模型,则应使用BackgroundWorker.ReportProgress
方法而不是BackgroundWorker.ReportProgress
(前提是您不需要后台线程来等待UI任务完成)。
如果您需要有关[[how的进一步帮助以重新编写代码,则需要发布Dispatcher.Invoke
的内容,这时我很乐意编辑答案以包括进一步的指导。