我是.net中线程模型的新手。你会用什么:
启动进程并等待应该在与主线程不同的线程上完成,因为此操作不应该影响应用程序。
示例:
我的应用程序生成一个HTML报告。用户可以右键单击某处并显示“查看报告” - 现在我在临时文件中检索报告内容并启动处理html文件的过程,即默认浏览器。问题是我无法清理,即删除临时文件。
答案 0 :(得分:60)
“等待必须是异步的” - 我不是想搞笑,但这不是一个矛盾吗?但是,由于您要开始Process
,Exited
事件可能有所帮助:
ProcessStartInfo startInfo = null;
Process process = Process.Start(startInfo);
process.EnableRaisingEvents = true;
process.Exited += delegate {/* clean up*/};
如果你想实际等待(超时等),那么:
if(process.WaitForExit(timeout)) {
// user exited
} else {
// timeout (perhaps process.Kill();)
}
等待异步,或许只是使用不同的线程?
ThreadPool.QueueUserWorkItem(delegate {
Process process = Process.Start(startInfo);
if(process.WaitForExit(timeout)) {
// user exited
} else {
// timeout
}
});
答案 1 :(得分:18)
为这个旧问题添加高级替代方案。如果要等待进程退出而不阻塞任何线程并仍然支持超时,请尝试以下操作:
public static Task<bool> WaitForExitAsync(this Process process, TimeSpan timeout)
{
ManualResetEvent processWaitObject = new ManualResetEvent(false);
processWaitObject.SafeWaitHandle = new SafeWaitHandle(process.Handle, false);
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
RegisteredWaitHandle registeredProcessWaitHandle = null;
registeredProcessWaitHandle = ThreadPool.RegisterWaitForSingleObject(
processWaitObject,
delegate(object state, bool timedOut)
{
if (!timedOut)
{
registeredProcessWaitHandle.Unregister(null);
}
processWaitObject.Dispose();
tcs.SetResult(!timedOut);
},
null /* state */,
timeout,
true /* executeOnlyOnce */);
return tcs.Task;
}
同样,与接受的答案相比,此方法的优势在于您不会阻止任何线程,从而减少了应用的开销。
答案 2 :(得分:4)
尝试以下代码。
public void KickOffProcess(string filePath) {
var proc = Process.Start(filePath);
ThreadPool.QueueUserWorkItem(new WaitCallBack(WaitForProc), proc);
}
private void WaitForProc(object obj) {
var proc = (Process)obj;
proc.WaitForExit();
// Do the file deletion here
}
答案 3 :(得分:0)
我可能不会使用单独的进程来打开文件。相反,我可能会使用后台线程(如果我认为操作需要很长时间并且可能阻止UI线程)。
private delegate void FileOpenDelegate(string filename);
public void OpenFile(string filename)
{
FileOpenDelegate fileOpenDelegate = OpenFileAsync;
AsyncCallback callback = AsyncCompleteMethod;
fileOpenDelegate.BeginInvoke(filename, callback, state);
}
private void OpenFileAsync(string filename)
{
// file opening code here, and then do whatever with the file
}
当然,这不是一个好的工作示例(它什么都不返回),我还没有展示UI如何更新(你必须在UI级别使用BeginInvoke,因为后台线程无法更新UI线程)。但这种方法通常是我如何处理.Net中的异步操作。
答案 4 :(得分:0)
您可以在Process类
中使用Exited
事件
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "notepad.exe";
Process process = Process.Start(info);
process.Exited += new EventHandler(process_Exited);
Console.Read();
在那种情况下,你可以处理你提到的操作