繁体   English   中英

如何使用一个线程来完成,然后重用该线程?

[英]How to use a thread to completion, then reuse the thread?

我正在构建一个表单,并且尝试使用线程以便从WMI查询中获取一些结果以显示在文本框中,而不会导致表单冻结在用户身上。 但是,当我使用下面的代码并在调试时使用Break-All时,代码仅位于getPrinterThread.Join() 我知道我一定很想念东西。

我的目的是让一个线程运行ObtainPrinterPort方法完成,然后让一个线程运行InstallPrinterPort方法完成。 我下面的代码作为另一种方法中的内联代码。 该代码不在单独的类中或任何其他类中,并且我没有后台工作人员,因为到目前为止,我所看到的所有示例都只是让我感到困惑。

这是我公认的糟糕的线程尝试:

Thread printThread = new Thread(ObtainPrinterPort);
printThread.Start();
while (!printThread.IsAlive) ;
Thread.Sleep(1);
printThread.Join();         // Form sits and does nothing; Break-all reveals this line as statement being executed.

Thread installThread = new Thread(InstallPrinterPort);
installThread.Start();
while (!installThread.IsAlive);
Thread.Sleep(1);
installThread.Join();

有没有一种简单的方法可以让我安全地工作,并允许我在文本框中向用户显示方法中发生的结果? 希望有一种方法可以使我继续使用在表单类中编写的实例变量/方法/代码...否则,如果我需要重新编写很多代码, m将实现“ DoWork”类型的示例 (其中,我的方法是从DoWork方法/构造函数或Worker类中调用的)。

请记住,我的方法需要将线程中的文本返回到文本框以向用户显示结果。 我假设我的代码可以让我从线程返回文本(如果可行的话),但是我只是想确保所有建议/帮助都牢记这一点。 我正在使用的代码如下:

public void AppendTextBox(string value)
{
    if (InvokeRequired)
    {
        this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
        return;
    }

    txtResults.Text += value;
}

对于它的价值,这是我的ObtainPrinterPort方法和它附带的CreateNewConnection方法... InstallPrinterPort方法非常相似,因此发布它并不会真正揭示​​太多:

private ManagementScope CreateNewConnection(string server, string userID, string password)
{
    string serverString = @"\\" + server + @"\root\cimv2";
    ManagementScope scope = new ManagementScope(serverString);

    try
    {
        ConnectionOptions options = new ConnectionOptions
        {
            Username = userID,
            Password = password,
            Impersonation = ImpersonationLevel.Impersonate,
            EnablePrivileges = true

        };
        scope.Options = options;
        scope.Connect();
    }
    catch (ManagementException err)
    {
        MessageBox.Show("An error occurred while querying for WMI data: " +
                        err.Message);
    }
    catch (System.UnauthorizedAccessException unauthorizedErr)
    {
        MessageBox.Show("Connection error (user name or password might be incorrect): " +                              unauthorizedErr.Message);
    }

    return scope;
}

private void ObtainPrinterPort()
{
    string computerName = "";
    string userID = "";
    string password = "";
    string printerQuery = "SELECT * FROM Win32_Printer WHERE Name = ";
    string portQuery = "SELECT * FROM Win32_TCPIPPrinterPort WHERE Name = ";
    string search = "";
    SelectQuery query;

    foreach (var s in lstServer)
    {
        computerName = s.ServerName;
        userID = s.UserID;
        password = s.Password;
    }

    ManagementScope scope = CreateNewConnection(computerName, userID, password);

    foreach (Printers p in lstPrinters)
    {
        AppendTextBox("Obtaining printer/port info for " + p.PrinterName + "\r\n");

        search = printerQuery + "'" + p.PrinterName + "'";

        query = new SelectQuery(search);

        try
        {
            using (var searcher = new ManagementObjectSearcher(scope, query))
            {
                ManagementObjectCollection printers = searcher.Get();

                if (printers.Count > 0)
                {
                    AppendTextBox("\tStoring printer properties for " + p.PrinterName + "\r\n");

                    foreach (ManagementObject mo in printers)
                    {
                        StorePrinterProperties(p, mo);
                    }
                }
                else
                {
                    lstPrinterExceptions.Add("Printer: " + p.PrinterName);

                    AppendTextBox("\t**Printer " + p.PrinterName + " not found**\r\n");
                }
            }
        }
        catch (Exception exception)
        {
            MessageBox.Show("Error: " + exception.Message, "Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        if (!lstPrinterExceptions.Contains("Printer: " + p.PrinterName)
           && !lstPrinterExceptions.Contains("Port: " + p.PortName))
        {
            search = portQuery + "'" + p.PortName + "'";

            query = new SelectQuery(search);

            try
            {
                using (var searcher = new ManagementObjectSearcher(scope, query))
                {
                    ManagementObjectCollection ports = searcher.Get();

                    if (ports.Count > 0)
                    {
                        AppendTextBox("\tStoring port properties for " + p.PortName + " (" + p.PrinterName + ")\r\n");

                        foreach (ManagementObject mo in ports)
                        {
                            StorePortProperties(p, mo);
                        }
                    }
                    else
                    {
                        lstPrinterExceptions.Add("Port: " + p.PortName);

                        AppendTextBox("\t**Port " + p.PortName + " for " + p.PrinterName + " not found**\r\n");
                    }
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show("Error: " + exception.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            AppendTextBox("\tSuccessfully obtained printer/port info for " + p.PrinterName + "\r\n");
        }
    }
}

谢谢。

您的问题是, Invoke调用正在阻塞,等待主线程进入DoEvents以便可以对其进行处理,但是主线程在Thread.Join处于阻塞状态。 你陷入僵局。

这是在不阻塞UI线程的情况下运行线程的方式。 Thread.Join阻塞直到另一个线程结束,所以这里我最多阻塞100毫秒,然后调用DoEvents以便表单可以响应消息(包括处理来自另一个线程的Invoke调用),然后循环直到后台线程完成。

Thread printThread = new Thread(ObtainPrinterPort);
printThread.Start();
while (printThread.IsAlive) {
    Application.DoEvents();        
    printThread.Join(100);        
}

在这样的循环中调用DoEvents有点麻烦,但是可以正常工作。

您还可以查看BackgroundWorker ,这使整个过程变得更加安全和轻松。

一个简单的例子:

var bw = new BackgroundWorker();            
bw.DoWork += (worker, args) => {
    ObtainPrinterPort();
};
bw.RunWorkerAsync();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM