0

在多线程应用程序中启动新进程时,我必须小心处理任何问题吗?

我在一个简单的项目中尝试了这个:

static void Main(string[] args)
{
    Process.Start(@"D:\System\Desktop\a.txt");
    MessageBox.Show("Success");
}

它运行完美。但是当我在使用多线程的大项目中执行此操作时,它的线程停止工作(“a.txt”已打开但“成功”未显示),而我的应用程序(其他线程)运行良好。

在这种情况下有什么问题?

4

3 回答 3

2

如果您有一个 Windows.Forms 应用程序并且您尝试从不是主用户界面线程的线程中显示消息框,则消息框的行为是未定义的。意思是,它可能显示也可能不显示、不一致或其他一些问题。

例如,显示来自 BackgroundWorker 的 DoWork 事件的消息框可能有效,也可能无效。在一种情况下,无论单击什么按钮,消息框结果总是取消。

因此,如果您仅出于调试目的使用消息框,请使用不同的技术。如果您必须显示一个消息框,请从主用户界面线程调用它。

控制台应用程序通常不会有显示消息框的问题。然而,我遇到过在消息框调用之前我必须让线程休眠 100 毫秒的情况。

请注意,正如 TomTom 所指出的,主要的用户界面线程是应用程序的 Windows 消息循环。这提醒了我,我曾经必须在控制台应用程序中创建一个表单才能创建一个 Windows 消息循环,以便我的应用程序可以响应 Windows 消息。

于 2011-12-30T08:13:14.957 回答
2

这不是答案- 我不能将所有这些代码放在评论中......

这对我有用。告诉我您的代码与此有何不同:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace Test
{
    class Program
    {
        const string OutputFile = @"E:\Output.txt";

        object _lock = new object();

        static void Main(string[] args)
        {
            Program program = new Program();

            Thread thread = new Thread(program.ThreadMethod);
            thread.Start(@"E:\Test.txt");

            thread = new Thread(program.ThreadMethod);
            thread.Start(@"E:\DoesntExist.txt");

            Console.ReadKey();
        }

        void ThreadMethod(object filename)
        {
            String result = RunNormal(filename as string);
            lock (_lock)
            {
                FileInfo fi = new FileInfo(OutputFile);
                if (!fi.Exists)
                {
                    try
                    {
                        fi.Create().Close();
                    }
                    catch (System.Security.SecurityException secEx)
                    {
                        Console.WriteLine("An exception has occured: {0}", secEx.Message);
                        return;
                    }
                }

                StreamWriter sw = fi.AppendText();
                sw.WriteLine(result);
                sw.Close();
            }
        }

        string RunNormal(string fullfilename)
        {
            try
            {
                Process.Start(fullfilename);
                return fullfilename + "|Success";
            }
            catch (Exception e)
            {
                return fullfilename + "|" + e.ToString();
            }
        }
    }
}

Output.txt 中的输出为:

E:\DoesntExist.txt|System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
   at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start(String fileName)
   at Test.Program.RunNormal(String fullfilename) in E:\Projekti\VS2010\Test\Test\Program.cs:line 59
E:\Test.txt|Success

你的代码有多大不同?你会调用其他方法吗?你如何处理结果?

于 2011-12-30T08:31:58.210 回答
0

确保Process.Start有效。在某些情况下,传递文件名还不够好。在您的示例代码中,您必须设置 use-shell 属性;否则,您将不得不使用cmd start <filename>或等效。

因此,只需启动 NotePad.exe 以确保Process.Start工作正常。如果是这样,那么您的问题是进程命令和命令行。

于 2011-12-30T08:25:26.217 回答