我希望有人能指出我正确的方向。我想制作一个简单的WPF应用程序,它有一个按钮和一个文本框。我点击按钮,它开始循环下载一堆文件。我似乎无法弄清楚如何不让下载阻止UI更新。根据我的收集,我可能不得不使用一些线程代码;但到目前为止,我发现并尝试过的所有例子都不适合我。对我应该去看和学习的任何帮助或方向都会很棒。我似乎无法弄清楚如何在每个文件下载周围输出这些textbox.text消息。
foreach (var ticker in tickers)
{
var url = string.Format(urlPrototype, ticker, startMonth, startDay, startYear, finishMonth, finishDay, finishYear, "d");
var csvfile = directory + "\\" + ticker.ToUpper() + ".csv";
tbOutput.Text += "Starting Download of : " + ticker + "\n";
webClient.DownloadFile(url, csvfile);
tbOutput.Text += "End Download of : " + ticker + "\n";
numStocks++;
}
tbOutput.Text += "Total stocks downloaded = " + numStocks + "\n";
答案 0 :(得分:6)
如果您将方法标记为 async ,则可以使用DownloadFileTaskAsync
方法
await webClient.DownloadFileTaskAsync(url, csvfile)
答案 1 :(得分:0)
有很多方法可以实现它。例如:
1)如果在.Net Framework 4.5中编程,则使用async / await。它比BackgroundWorker
简单https://msdn.microsoft.com/en-us/library/hh191443.aspx
$(document).ready(function () {
$('.clock').each(function () {
var clock;
clock = $(this).FlipClock({
clockFace: 'DailyCounter',
autoStart: false,
callbacks: {
stop: function () {
$('.message').html('The clock has stopped!')
}
}
});
clock.setTime(220880);
clock.setCountdown(true);
clock.start();
})
});
2)BackgroundWorker。此类实际上旨在进行异步操作以避免冻结UI。 见http://www.wpf-tutorial.com/misc/multi-threading-with-the-backgroundworker
private async void button_Click(object sender, RoutedEventArgs e)
{
Uri someUrl=new Uri(@"http://dotnetperls.com");
WebClient webClient=new WebClient();
await webClient.DownloadFileTaskAsync(someUrl, csvFile);
}
3)使用Thread类并使用Dispatcher类进行更新:
public partial class MainWindow : Window
{
BackgroundWorker bw;
public MainWindow()
{
InitializeComponent();
bw = new BackgroundWorker();
bw.DoWork += bw_DoWok;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
}
}
void bw_RunWorkerComleted(object sender, RunWorkerCompletedEventAgs e)
{
MessageBox.Show("The result is " + e.Result.ToString());
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var ticker in tickers)
{
var url = string.Format(urlPrototype, ticker, startMonth, startDay, startYear, finishMonth, finishDay, finishYear, "d");
var csvfile = directory + "\\" + ticker.ToUpper() + ".csv";
webClient.DownloadFile(url, csvfile);
numStocks++;
}
e.Result = "End Of Download ";
}
private void button_Click(object sender, RoutedEventArgs e)
{
bw.RunWorkerAsync();
tbOutput.Text += "Starting Download of : " + ticker + "\n";
}
http://www.beingdeveloper.com/use-dispatcher-in-wpf-to-build-responsive-applications
答案 2 :(得分:0)
如果您选择使用BackgroundWorker,它允许您在每个文件下载周围将这些消息输出到TextBox中。这是一个适合您要求的粗略示例。
1)在类级别,创建BackgroundWorker类的实例并将事件处理程序添加到BackgroundWorker实例的事件中:
BackgroundWorker workerDownload = new BackgroundWorker();
workerDownload.WorkerReportsProgress = true;
workerDownload.DoWork += workerDownload_DoWork;
workerDownload.ProgressChanged += workerDownload_ProgressChanged;
workerDownload.RunWorkerCompleted += workerDownload_RunWorkerCompleted;
2)为后台工作人员的DoWork事件创建一个事件处理程序:
DoWork事件处理程序是您运行耗时操作的地方 在后台线程。传递给后台的任何值 操作在DoWorkEventArgs的Argument属性中传递 传递给事件处理程序的对象。
private void workerDownload_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var ticker in tickers)
{
// you can pass the required info as argument:
string[] arrArg = (string[])e.Argument;
string theUrl = arrArg[0];
string directory = arrArg[1];
var url = string.Format(theUrl, ticker);
var csvfile = directory + "\\" + ticker.ToUpper() + ".csv";
// perform the download operation and report progress:
workerDownload.ReportProgress(0, "Starting Download of : " + ticker + "\n");
webClient.DownloadFile(url, csvfile);
workerDownload.ReportProgress(100, "End Download of : " + ticker + "\n");
numStocks++;
}
}
3)为后台工作者的ProgressChanged事件创建一个事件处理程序:
在ProgressChanged事件处理程序中,添加代码以指示 进度,例如更新用户界面。
private void workerDownload_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tbOutput.Text += e.UserState.ToString();
}
4)为RunWorkerCompleted事件创建一个事件处理程序:
后台工作者具有RunWorkerCompleted事件 完成。
private void workerDownload_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
tbOutput.Text += "Total stocks downloaded = " + numStocks + "\n";
}
5)通过调用RunWorkerAsync方法开始运行后台操作:
int numStocks = 0;
string strDirectory = "<a_directory>";
string strUrl = string.Format(urlPrototype, startMonth, startDay, startYear, finishMonth, finishDay, finishYear, "d");
string[] args = new string[2] { strUrl, strDirectory };
workerDownload.RunWorkerAsync(args);