C# 从连续运行的exe文件中删除闪烁
我有几个.exe文件,我运行如下:C# 从连续运行的exe文件中删除闪烁,c#,windows,winapi,C#,Windows,Winapi,我有几个.exe文件,我运行如下: public void RunCalculator(Calculator calculator) { var query = Path.Combine(EpiPath, calculator.ExeName + ".exe"); if (File.Exists(Path.Combine(EpiPath, "ffs.exe"))) { var p = new Process(
public void RunCalculator(Calculator calculator)
{
var query = Path.Combine(EpiPath, calculator.ExeName + ".exe");
if (File.Exists(Path.Combine(EpiPath, "ffs.exe")))
{
var p = new Process();
p.StartInfo.FileName = query;
p.StartInfo.WorkingDirectory = EpiPath;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.Arguments = String.Join(" ", calculator.Arguments);
p.Start();
p.WaitForExit();
}
else throw new InvalidOperationException();
}
这段代码可以工作,但仍然有一些闪烁是由多次运行exe-s引起的。有没有办法消除闪烁,因为它真的很烦人的用户体验,因为它发生了几秒钟(有相当多的exe正在运行)
我尝试使用一个任务在不同的线程上执行,但由于每个exe都依赖于前一个线程(它写入文件)上的工作,因此我得到了一个IO异常
似乎exe文件只有在ProcessPriority设置为Realtime时才能工作
编辑:
有关我最近尝试的内容的更多详细信息:
正如@Jack Hughes建议的那样,我尝试使用一名背景工作者来解决这个问题:
以下是我所做的:
我在后台工作程序上调用RunWorkerAsync()函数,然后依次为每个计算器调用RunCalculator函数。闪烁仍然存在
编辑2:
我已经创建了一个详细的存储库,其中包含我运行exe文件、exe文件和ProcessHelper类的方式,这是Old Fox建议的。
您可以在自述文件中找到有关如何使用存储库的说明
链接到存储库:将工作放在后台线程中,这样就不会阻塞主GUI线程 大概是这样的:
public class MainWindow : Window
{
private readonly BackgroundWorker worker = new BackgroundWorker();
public MainWindow()
{
this.Loaded += MyWindow_Loaded;
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
private void MyWindow_Loaded(object sender, RoutedEventArgs e)
{
// Start the background worker. May be better started off on a button or something else app specific
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// run all .exes here...
// Note: you cannot access the GUI elements directly from the background thread
RunCalculator();
RunOtherExes();
}
private void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
//update ui once worker complete its work
}
private void RunCalculator()
{
var p = new Process();
p.StartInfo.FileName = query;
p.StartInfo.WorkingDirectory = path;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.Arguments = String.Join(" ", calculator.Arguments);
p.Start();
p.WaitForExit();
}
private void RunOtherExes()
{
// ...
}
}
如果需要,您也可以使用后台线程的进度更新GUI线程。我遇到了与您在使用C#创建ActiveX
扩展时描述的相同的“闪烁”问题。扩展必须启动一个隐藏的控制台应用程序
,但是每次我启动应用程序时,控制台都会出现几毫秒
为了解决这个问题,我尝试了很多方法,比如:获取进程
类的源代码并进行调试,UAC
检查,VM
与真实机器的对比等等
我找到的解决方案是使用Win32Api
。以下代码段启动了一个没有“闪烁”的新进程:
这不是一个好的解决方案!然而,只有当你开始一个过程时,你才需要睡眠。。。所以我试着利用这些信息:
private void Button_Click(object sender, RoutedEventArgs e)
{
var ac = new Action(() => Application.Current.Dispatcher.Invoke(
() =>
{
Thread.Sleep(50);
}));
Task.Factory.StartNew(() =>
{
//Provide path to epi
string epiPath = @"c:/EPISUITE41";
Level3ntCalculator cl = new Level3ntCalculator();
var runner = new Calculators.Epi.Runners.ProcessRunner(epiPath, ac);
runner.WriteXSmilesFiles("CCCCC1CCCCCCC1");
cl.Calculate(runner);
});
}
然后我更改了ProcessRunner
:
public void RunCalculator(Calculator calculator)
{
//bla bla bla...
new Thread(new ThreadStart(_action)).Start();
p.Start();
//...
}
在此代码段中,您在UI
线程中执行Thread.Sleep
的时间非常短(用户永远不会知道…)
这是一个糟糕的解决方案。。。但是它解决了问题。仍然不清楚您正在经历什么样的闪烁,但是您在GUI线程上执行
WaitForExit()
这一事实看起来很麻烦。考虑到您正在运行一个外部程序,我真的看不到从另一个线程启动它并等待的意义,也许使用Exited
事件而不是阻塞等待将释放GUI线程来完成其工作并停止问题
不要忘记将
EnableRaisingEvents
设置为true,并且IIRC将在线程池上引发事件,因此在触摸任何控件之前返回到UI上下文。您所说的“闪烁”是什么意思?exe将运行,它们执行一些计算和一些IO操作,然后关闭。运行每个exe后,它将关闭,然后打开下一个exe。它们每个执行的操作都会导致整个窗口闪烁(我认为这与Windows的操作方式有关)。您是否从GUI线程启动上述操作以及其他许多操作?如果您正在GUI线程上做大量工作,并等待结果,那么您将阻止GUI更新。当它最终更新自己时,它可能看起来像是在闪烁。将您的处理放在后台线程中,并尽可能使主GUI线程保持空闲。@JackHughes,您能举个例子吗。我尝试使用一个任务在不同的线程上执行该任务,但由于每个exe都取决于前一个线程的工作(它写入文件),因此我得到了一个IO异常。如果查看接受的答案,您会发现一个很好的示例,说明如何执行该任务。如果我这样做,exe文件的执行顺序是否会同步?我需要它是同步的,以便得到正确的输出。这意味着我必须确保在执行exe文件B之前完成exe文件A。是<首先执行code>RunCalculator,并对进程调用WaitForExit
,以便后台线程在启动下一个进程之前等待进程结束。然后调用RunOtherExes
,这将对其他进程执行相同的操作。不幸的是,使用此方法仍然会导致闪烁。您可以发布项目的其余部分吗?由于保密协议,我不允许发布我正在处理的项目。我已经在我的问题tho中解释了大部分实现。感谢您的回复。我在没有WaitForExit的情况下尝试了相同的操作,但使用了一个timout,结果是一样的。UI线程上的任何等待都可能会导致问题,无论超时如何。如果不使用此方法运行Exe,可能会更改进程的优先级?不太清楚原因。如何执行方法ProcessHelper.StartProcess
?(行的外观)请验证该进程未在任务管理器
(进程选项卡)中启动。如果您愿意,我可以将一个示例上载到github。为什么不应该在任务管理器流程中启动该流程?无论如何,很难跟踪进程是否已启动,因为它几乎立即退出。我的错误是,您应该在任务管理器
(进程选项卡)中看到它,但不应该在应用程序
选项卡中看到它。现在我正在使用linux机器。稍后(大约5个小时后)我将上传一个工作示例。我会看看它是否适合用例并回复。你应得的赏金,虽然这个解决方案可能会被证明是有用的,但我想我最终将不得不伪装成应用程序,看看能做些什么。附言:我已经知道了
private void Button_Click(object sender, RoutedEventArgs e)
{
var ac = new Action(() => Application.Current.Dispatcher.Invoke(
() =>
{
Thread.Sleep(50);
}));
Task.Factory.StartNew(() =>
{
//Provide path to epi
string epiPath = @"c:/EPISUITE41";
Level3ntCalculator cl = new Level3ntCalculator();
var runner = new Calculators.Epi.Runners.ProcessRunner(epiPath, ac);
runner.WriteXSmilesFiles("CCCCC1CCCCCCC1");
cl.Calculate(runner);
});
}
public void RunCalculator(Calculator calculator)
{
//bla bla bla...
new Thread(new ThreadStart(_action)).Start();
p.Start();
//...
}