我在WPF应用程序中有以下代码,在长时间运行的进程发生时显示启动画面。在我们所有的开发人员机器和测试机器上,这都非常有效。但是在某些客户机器上,此代码会使主进程继续运行。
我尝试了各种调用关机的方法,包括Environment.Exit(0);
,我们仍然看到此过程在完成后仍然运行。
关于我的任务和应用程序如何交互,我有什么遗漏?
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace GKUpdate
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
MainWindow oWindow;
string sPipeName;
string sGKPath;
//Call base startup
base.OnStartup(e);
//Find the GK path
sPipeName = FindArgument(e.Args, "n");
sGKPath = FindArgument(e.Args, "p");
//Check if we have a path
if (!string.IsNullOrEmpty(sGKPath))
{
//Start listening
Task.Factory.StartNew(() => ListenForSuccess(sPipeName, sGKPath));
//Show the splash window
oWindow = new MainWindow();
oWindow.Show();
}
else
{
//Exit
this.Shutdown();
}
}
private string FindArgument(string[] oArgs, string sArgumentName)
{
string sFilter;
string sArgument;
//Get the argument
sFilter = string.Format("/{0}=", sArgumentName).ToLower();
sArgument = oArgs.FirstOrDefault(x => x.ToLower().StartsWith(sFilter));
//Check if we found the argument
if (!string.IsNullOrEmpty(sArgument) && sArgument.Length > sFilter.Length)
{
//Set the argument
sArgument = sArgument.Substring(sFilter.Length).Trim('"');
}
else
{
//Set null
sArgument = null;
}
//Return the argument
return sArgument;
}
private void ListenForSuccess(string sPipeName, string sGKPath)
{
int iStatus;
try
{
//Set default status
iStatus = -1;
//Loop until the service is online
do
{
//Create the named pipe
using (NamedPipeClientStream oNamedPipe = new NamedPipeClientStream(".", sPipeName, PipeDirection.InOut))
{
//Connect the pipe allowing 5 mins
oNamedPipe.Connect(300000);
//Send the byte asking for a status report
oNamedPipe.WriteByte(0);
oNamedPipe.WaitForPipeDrain();
//Read the return
iStatus = oNamedPipe.ReadByte();
//Disconnect
oNamedPipe.Close();
}
} while (iStatus != 1);
//Check if we can do the success actions
if (iStatus == 1)
{
//Start GateKeeper using the remaining command arguments
Process.Start(sGKPath, string.Join(" ", Environment.GetCommandLineArgs().Skip(3)));
}
}
catch (Exception)
{
//Do nothing
}
finally
{
//Exit the application
Application.Current.Dispatcher.InvokeShutdown();
}
}
}
}
答案 0 :(得分:0)
检查Threads
窗口是visual studio。当您的应用程序关闭时,您的一个非后台线程没有运行完成。我希望你现在还在“倾听”。
您如何处理此事取决于您,但我建议您实施task cancellation。
答案 1 :(得分:0)
可能有多种原因。首先,您必须检查窗口事件查看器,您将能够找到实际原因。
你也应该处理DispatcherUnhandledException =“Application_DispatcherUnhandledException”。这将显示实际错误。
App.XAML中的:
DispatcherUnhandledException="Application_DispatcherUnhandledException"
并在App.cs中:
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
}
答案 2 :(得分:0)
您的后台线程被阻塞,等待管道连接。您需要使用oNamedPipe.Close()从前台线程关闭管道。正如Erno de Weerd所说,您还需要确保在管道中止后退出do / while循环。
更好的方法是将CancellationToken传递给任务,并在前台线程请求取消时使用它来关闭管道。然后,您还可以在循环中检查取消状态。
答案 3 :(得分:0)
请参阅How to force Task.Factory.StartNew to a background thread?将Task.Factory.StartNew标记为后台线程,以便一旦所有&#39;前景&#39;线程已停止执行:
Task.Factory.StartNew(动作, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ContinueWith(completeAction);