我正在尝试创建一个文件复制应用程序。我有一个 BackgroudWorker 做这项工作,到目前为止它工作正常。它是如何工作的,我有一个表单、源文件夹和目标文件夹字段以及一个复制按钮。Copy 按钮使用 BackgroundWorker 触发 Copy 操作。进度条得到更新等。现在我需要实现一个队列类型的操作。我需要添加其他源和目标复制操作并将其添加到队列中。我尝试使用以下内容:
Queue<MethodInvoker> MyQueue = new Queue<MethodInvoker>();
MyQueue.Enqueue(new MethodInvoker(() =>CopyStuff(1)));
MyQueue.Enqueue(new MethodInvoker(() =>CopyStuff(2)));
MethodInvoker bb = MyQueue.Dequeue(); //(I Forgot this part)
bb();
bb = MyQueue.Dequeue();
bb();
问题是,因为它是一个 BackgroundWorker,它不会等待第一个操作完成。关于如何解决这个问题的任何建议?
修复我的代码后,它可以工作,除了它在 UI 线程上运行,锁定控件。
更新1:
这可行,但在主线程上运行,用户在运行时无法使用控件:
BlockingCollection<MethodInvoker> bCollection = new BlockingCollection<MethodInvoker>(boundedCapacity: 2);
Task producerThread = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 2; ++i)
{
bCollection.Add(CopyStuff);
}
bCollection.CompleteAdding();
});
foreach (MethodInvoker item in bCollection.GetConsumingEnumerable())
{
BeginInvoke(item);
}
更新 2:
适用于控制台应用程序,但不适用于 Windows 窗体应用程序。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AsyncCopy
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public class AsyncCopy
{
private static Queue<Action> MyQueue = new Queue<Action>();
public async Task EnqueueAndCopy(Action[] actionList)
{
foreach (var action in actionList)
{
MyQueue.Enqueue(action);
}
while (MyQueue.TryDequeue(out var copyAction)) //Here's the problem on Windows Form Applivcation
{
//If the copyaction is itself async, await directly on the method here instead of running the action in a Task
await Task.Factory.StartNew(copyAction);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
var asyncCopy = new AsyncCopy();
//In a typical usage, this will call be awaited
//In your case, make this call from a async method and call it from the UI thread
asyncCopy.EnqueueAndCopy(
new Action[] {
() => CopyStuff (1),
() => CopyStuff (2)
}
);
//Loop to confirm the processing is asynchronous
for (int i = 0; i <= 20; i++)
{
Console.WriteLine($"{i}");
Thread.Sleep(300);
}
}
//Copy process simulation
static void CopyStuff(int i)
{
Console.WriteLine($"Copying {i}");
Thread.Sleep(3000);
Console.WriteLine($"Copied {i}");
}
}
}