线程无法在C#控制台应用程序中启动

时间:2016-12-29 20:35:27

标签: c# multithreading

我正在尝试在以下未完成的代码中运行一个线程。其基本内容如下;当控制台应用程序启动时,它应该启动一个将关闭的线程,导航到一个网页(最终会进行一些处理),然后停止并终止单独的线程。结合使用,主应用程序将仅向用户提供菜单,直到退出应用程序。最后导航线程将被放入一个单独的方法,以便每隔一段时间定期调用一次,但这不应该与这个问题相关,我不认为......

我的理解是,单独的线程应该与主控制台应用程序一起运行,并在它完成任务时终止,就像控制台一样,如果你不阻止它退出????? 它实际上看起来是因为我没有通过browser_DocumentCompleted事件触发得到响应而没有首先开始(我知道IP地址是活动的并且是活动的,因为我已经检查过!!)

任何人都可以解释为什么单独的线程没有运行,或者看起来不是?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace ConsoleThreadTest
{
class Program
{
    public delegate void Callback(string Status);

    static void Main(string[] args)
    {

        NavigateToIPAddress GEIPA = new NavigateToIPAddress(new Uri("http://192.168.1.254"), new Callback(ResultCallback));
        Thread PerformThreadTask = new Thread(new ThreadStart(GEIPA.PerformThreadTask));
        PerformThreadTask.SetApartmentState(ApartmentState.STA);
        PerformThreadTask.Start();

        Console.WriteLine("{0}","Press escape key to exit");

        while (true)
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo key = Console.ReadKey(true);
                switch (key.Key)
                {
                    case ConsoleKey.Escape:
                        //Kill off thread if it is still running.
                        if (PerformThreadTask.ThreadState == ThreadState.Running)
                        {
                            PerformThreadTask.Abort();
                        }
                        Environment.Exit(0);
                        break;
                    default:
                        break;
                }
            }
        }

    }

    public static void ResultCallback(string Status)
    {
        Console.WriteLine("{0}\t{1}", DateTime.Now.ToString("h:mm:ss"), Status);
    }

    public class NavigateToIPAddress
    {
        private Uri WebAddress;
        private bool WebBrowserNavigationComplete = false;

        // Delegate used to execute the callback method when the task is complete.
        private Callback callback;

        // The constructor obtains the state information and the callback delegate.
        public NavigateToIPAddress(Uri IPAddressToNavigateTo, Callback callbackDelegate)
        {
            WebAddress = IPAddressToNavigateTo;
            callback = callbackDelegate;
        }

        // The thread procedure performs the task and then invokes the callback delegate with the status.
        public void PerformThreadTask()
        {
            var br = new WebBrowser();
            br.DocumentCompleted += browser_DocumentCompleted;
            try
            {
                br.Navigate(WebAddress);
            }
            catch (Exception e)
            {
                Console.WriteLine("{0}\tSome error occurred: {1}", DateTime.Now.ToString("h:mm:ss"), e.Message);
            }

            Application.Run();

            while (WebBrowserNavigationComplete == false)
            {
            }

            if (callback != null)
                callback("Summit occurred");
        }

        private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            var br = sender as WebBrowser;
            if (br.Url == e.Url)
            {
                Console.WriteLine("{0}\tNavigated to {1}", DateTime.Now.ToString("h:mm:ss"), e.Url);
                WebBrowserNavigationComplete = true;
            }
        }
    }
}
}

这里我有一个捕获22的情况。一方面,如果我保留上面的代码,application.run()方法之后的任何内容都不会被执行,这意味着WebBrowserNavigationComplete标志永远不会改变,并且永远不会返回回调。
但是,如果我在

之后移动application.run()
if (callback != null)
  callback("Summit occurred");

代码永远不会到达这一点,以便调用application.run(),因为它停留在等待WebBrowserNavigationComplete标志的while循环中,该标志永远不会因消息循环从未启动而改变!!

我不敢相信我是第一个做这样的事情的人?克服这种僵局的正常方法是什么?

谢谢

1 个答案:

答案 0 :(得分:1)

WebBrowser是一个winforms构造,需要设置一个应用程序循环来处理它的消息。由于您有一个控制台应用程序而没有消息循环,它将无法正常运行。

您需要使用Application.Run(需要从STA线程运行)显式创建新的应用程序循环才能使其正常工作。