如何在不冻结WPF C#中的UI屏幕的情况下与后台工作程序一起运行while循环? [重复]

问题描述 投票:0回答:1

此问题已经在这里有了答案:

我正在一个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,后台工作程序和并行处理的地方。

c# wpf backgroundworker
1个回答
3
投票

正如注释中所指出的那样,您提供的代码表明您实际上正在UI线程上运行所有工作。

[当您调用RunWorkerAsync时,BackgroundWorker开始运行循环,然后循环使用startPhantomEntranceEvaluation在UI线程上运行Dispatcher.Invoke。因此,您要做的就是调用后台线程再次调用UI线程。没有任何实际工作在后台完成。

您需要重新编写代码,以便仅在/当您需要更新UI时才使用Dispatcher.Invoke。另外,如果要坚持使用BackgroundWorker模型,则应使用BackgroundWorker.ReportProgress方法而不是BackgroundWorker.ReportProgress(前提是您不需要后台线程来等待UI任务完成)。

如果您需要有关[[how的进一步帮助以重新编写代码,则需要发布Dispatcher.Invoke的内容,这时我很乐意编辑答案以包括进一步的指导。

© www.soinside.com 2019 - 2024. All rights reserved.