我在我的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不起作用。但完成连接后一切都还可以! 请帮帮我! 提前谢谢!
答案 0 :(得分:7)
您正在调用ConnectFTP
方法的worker中的UI线程。你需要这个......
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.
}
答案 1 :(得分: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 { }
}));