1

我在我的 wpf 应用程序中使用 BackgroundWorker 进行线程处理。但这会使 UI 挂起,因为我无法单击 UI 的任何位置。这是我的代码片段:

private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            Dispatcher.Invoke(new Action(() => ConnectFtp()));
        };
        worker.RunWorkerAsync();
    }

private void ConnectFtp()
{
     try
        {
            int port = string.IsNullOrEmpty(txtport.Text) ? 21 : Convert.ToInt32(txtport.Text);
            if (ftpserver1 == null)
            {
                ftpserver1 = new FtpClient(txtftpserver.Text, port);
                ftpserver1.ServerResponse += new EventHandler<FtpResponseEventArgs>(ftpserver2_ServerResponse);
                ftpserver1.ClientRequest += new EventHandler<FtpRequestEventArgs>(ftpserver2_ClientRequest);
                ftpserver1.TransferProgress += new EventHandler<TransferProgressEventArgs>(ftpserver2_TransferProgress);
                ftpserver1.TransferComplete += new EventHandler<TransferCompleteEventArgs>(ftpserver2_TransferComplete);
            }
            if (!ftpserver1.IsConnected)
            {
                Run r = new Run("Server1 Status:    Resolving address of " + txtftpserver.Text + "\n" + "Server1 Status:    Connection established, waiting for welcome message... \n");
                r.Foreground = System.Windows.Media.Brushes.Black;
                msg.Inlines.Add(r);
                msgscroll.ScrollToBottom();                   
                ftpserver2_OpenAsyncCompleted(ftpserver1, txtusername.Text, txtpassword.Password);
            }
        }
        catch { }
}

在 ConnectFtp() 方法中,我连接到 ftp 服务器。当 ftp 服务器的连接状态为“正在连接”时,UI 不起作用。但完成连接后一切正常!请帮帮我!提前致谢!

4

2 回答 2

7

您正在调用该方法的工作人员内的 UI 线程ConnectFTP。你需要有这个...

BackgroundWorker _worker = new BackgroundWorker();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _worker.DoWork += delegate(object s, DoWorkEventArgs args)
    {
        ConnectFtp();
    };
    _worker.RunWorkerAsync();
}

private void ConnectFtp()
{
 //here i'm connecting to a ftp server. 
}
于 2012-09-06T05:42:16.977 回答
1

您正在将完整的方法从后台工作人员转储到 UI 线程Dispatcher 。这里

Dispatcher.Invoke(new Action(() => ConnectFtp()));


private void Window_Loaded(object sender, RoutedEventArgs e)
{
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            ConnectFtp();
        };
        worker.RunWorkerAsync();
}

private void ConnectFtp()
{
     // Here i'm connecting to a ftp server. 
     // Do some I/O operation
     // Now time to update UI controls so we invoke on Dispatcher UI thread
     Dispatcher.Invoke(new Action(() =>
     {
         lblMessage.Text = "Process finished";
         // Some other UI updates..
     }));
}

我想最好利用 .NET 4.0 中可用的Task Parallel Api,它在多核系统上运行良好,即真正的并行线程。使用 TPL 的优点是它对变量和 UI 元素使用闭包,因此您可以访问不同线程上的值,如果有时它不起作用,则在 Task 启动之前创建局部变量并在 Action 方法主体中使用它并使用 Dispatcher 更新 UI 控件调用..

例如:

using System.Threading;
using System.Threading.Tasks;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
        Task TWorkOnFTP = new TaskFactory().StartNew(ConnectFtp);
}

private void ConnectFtp()
{
     // Here i'm connecting to a ftp server. 
     // Do some I/O operation
     // Now time to update UI controls so we invoke on Dispatcher UI thread
     Dispatcher.Invoke(new Action(() =>
     {
         lblMessage.Text = "Process finished";
         // Some other UI updates..
     }));
}

其他相关参考:

更新

根据更新的问题,TPL 可以按如下方式使用:

    //Closures
    var strPort = txtport.Text;
    var strFTPServer = txtftpserver.Text;
    var strUserName = txtusername.Text;
    var strPassword = txtpassword.Password;

    //Start Task thread
    Task TProcessFTP = new TaskFactory().StartNew(new Action(() =>
    {
        try
        {
            int port = string.IsNullOrEmpty(strPort) ? 21 : Convert.ToInt32(strPort);
            if (ftpserver1 == null)
            {
                ftpserver1 = new FtpClient(strFTPServer, port);
                ftpserver1.ServerResponse += new EventHandler<FtpResponseEventArgs>(ftpserver2_ServerResponse);
                ftpserver1.ClientRequest += new EventHandler<FtpRequestEventArgs>(ftpserver2_ClientRequest);
                ftpserver1.TransferProgress += new EventHandler<TransferProgressEventArgs>(ftpserver2_TransferProgress);
                ftpserver1.TransferComplete += new EventHandler<TransferCompleteEventArgs>(ftpserver2_TransferComplete);
            }
            if (!ftpserver1.IsConnected)
            {
                //Update UI Controls
                Dispatcher.Invoke(new Action(() =>
                {
                    Run r = new Run("Server1 Status:    Resolving address of " + txtftpserver.Text + "\n" + "Server1 Status:    Connection established, waiting for welcome message... \n");
                    r.Foreground = System.Windows.Media.Brushes.Black;
                    msg.Inlines.Add(r);
                    msgscroll.ScrollToBottom();
                    ftpserver2_OpenAsyncCompleted(ftpserver1, strUserName, strPassword);
                }));
            }
        }
        catch { }
    }));
于 2012-09-06T05:56:17.987 回答