我在WPF中有以下代码,我的问题是:
txtResult1.text
个事件中写txtResult2.text
,txtResult3.text
,worker_DoWork
。但是如何解决这个问题?ReadLineAsync
和WriteLineAsync
吗?这是我的代码:
public MainWindow()
{
InitializeComponent();
}
private readonly BackgroundWorker worker = new BackgroundWorker();
private void btnStart_Click(object sender, RoutedEventArgs e)
{
worker.DoWork +=worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.WorkerReportsProgress = true;
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
Parallel.Invoke(() =>
{ Task.Run(() => txtResult1.text = ReadCharacter("C:\\File 1.txt")); },
() =>
{ Task.Run(() => txtResult2.text = ReadCharacter("C:\\File 2.txt")); },
() =>
{ Task.Run(() => txtResult3.text = ReadCharacter("C:\\File 3.txt")); }
);
}
private string ReadCharacter(string inputFile)
{
string result; string TID;
using (StreamReader sr =new StreamReader(inputFile))
using (StreamWriter sw = new StreamWriter(string.Format("{0}--Out.txt", inputFile.Replace(".txt",""))))
{
var sb = new StringBuilder();
TID = "Thread ID: "+ Thread.CurrentThread.ManagedThreadId.ToString();
sb.AppendLine(TID);
sb.AppendLine("T Start : " + DateTime.Now.ToLongTimeString() + "." +
DateTime.Now.Millisecond).ToString();
while (!sr.EndOfStream)
{
result = sr.ReadLine();
sw.WriteLine(result);
};
return
sb.AppendLine("T Stop : "+DateTime.Now.ToLongTimeString() + "." +
DateTime.Now.Millisecond).ToString();
}
}
答案 0 :(得分:1)
您的方法存在一些问题:
Task.Run
,则Parallel.Invoke
不会向您购买任何东西
如果你想做并发I / O ,那么Parallel
是错误的解决方案 - Parallel
用于并行CPU绑定操作。BackgroundWorker
在这一点上几乎是遗产。我有blog series that shows how Task.Run
is better than BackgroundWorker
。另外,正如@HansPassnat指出的那样,你几乎肯定会不想要并发磁盘访问,因为这通常会大大减慢你的速度。
但如果你真的想这样做,我建议采用async
方法:
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
var progress = new Progress<string>(value => { txtResult1.Text = value; });
await Task.WhenAll(ReadCharacterAsync("C:\\File 1.txt", progress),
ReadCharacterAsync("C:\\File 2.txt", progress),
ReadCharacterAsync("C:\\File 3.txt", progress));
MessageBox.Show("Done");
}
private async Task ReadCharacterAsync(string inputFile, IProgress<string> progress)
{
string result; string TID;
using (var inFile = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.None, 8192, useAsync: true))
using (var outFile = new FileStream(string.Format("{0}--Out.txt", inputFile.Replace(".txt","")), FileMode.Create, FileAccess.ReadWrite, FileShare.None, 8192, useAsync: true))
using (StreamReader sr =new StreamReader(inFile))
using (StreamWriter sw = new StreamWriter(outFile))
{
var sb = new StringBuilder();
TID = "Thread ID: "+ Thread.CurrentThread.ManagedThreadId.ToString();
sb.AppendLine(TID);
sb.AppendLine("T Start : " + DateTime.Now.ToLongTimeString() + "." +
DateTime.Now.Millisecond).ToString();
while (!sr.EndOfStream)
{
result = await sr.ReadLineAsync();
await sw.WriteLineAsync(result);
};
progress.Report(
sb.AppendLine("T Stop : "+DateTime.Now.ToLongTimeString() + "." +
DateTime.Now.Millisecond).ToString());
}
}
答案 1 :(得分:0)
在WPF中,您必须使用Dispatcher访问其他线程的控件:
Parallel.Invoke(() =>
{ Task.Run(() => this.Dispatcher.BeginInvoke(new Action(() =>
txtResult1.Text += ReadCharacter("C:\\File 2.txt")); },
)
答案 2 :(得分:0)
您必须在处理事件的同一线程上设置文本框。您可以通过Task
的{{1}}方法或在下面显示的方法中使用async / await(或其他解决方案中描述的.ContinueWith(...)
方法)来执行此操作:
Dispatcher.BeginInvoke
用法:
private async Task GetDataAndSetTextBoxAsync( TextBox textBox, Func<char> dataMethod )
{
var task = Task.StartNew( taskMethod );
await task;
// this will run on thread that called this method
// in a WPF application
textBox.Text = task.Result;
}