使用C#Queue<;MethodInvoker>;
我正在尝试创建一个文件复制应用程序。我有一个工作背景的人在做这项工作,到目前为止效果很好。如何工作,我有一个表单,源和目标文件夹字段和一个复制按钮。复制按钮使用BackgroundWorker触发复制操作。Progressbar得到更新等。现在我需要实现一个队列类型的操作。我需要添加其他源和目标复制操作,并将其添加到队列中。我尝试使用以下方法:使用C#Queue<;MethodInvoker>;,c#,queue,filecopy,C#,Queue,Filecopy,我正在尝试创建一个文件复制应用程序。我有一个工作背景的人在做这项工作,到目前为止效果很好。如何工作,我有一个表单,源和目标文件夹字段和一个复制按钮。复制按钮使用BackgroundWorker触发复制操作。Progressbar得到更新等。现在我需要实现一个队列类型的操作。我需要添加其他源和目标复制操作,并将其添加到队列中。我尝试使用以下方法: Queue<MethodInvoker> MyQueue = new Queue<MethodInvoker>();
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();
Queue MyQueue=new Queue();
Enqueue(新的MethodInvoker(()=>CopyStuff(1));
Enqueue(新的MethodInvoker(()=>CopyStuff(2));
MethodInvoker bb=MyQueue.Dequeue()//(我忘了这部分)
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);
}
BlockingCollection bCollection=新的BlockingCollection(边界容量:2);
Task ProducerRead=Task.Factory.StartNew(()=>
{
对于(int i=0;i<2;++i)
{
b collection.Add(CopyStuff);
}
b collection.CompleteAdding();
});
foreach(bCollection.GetConsumingEnumerable()中的MethodInvoker项)
{
BeginInvoke(项目);
}
更新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}");
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统线程;
使用System.Threading.Tasks;
使用System.Windows.Forms;
命名空间异步复制
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
}
公共类异步复制
{
私有静态队列MyQueue=新队列();
公共异步任务排队和复制(操作[]操作列表)
{
foreach(操作列表中的var操作)
{
MyQueue.Enqueue(操作);
}
while(MyQueue.TryDequeue(out var copyAction))//这是Windows窗体应用程序的问题
{
//如果copyaction本身是异步的,请在此处直接等待该方法,而不是在任务中运行该操作
等待任务.Factory.StartNew(copyAction);
}
}
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
var asyncCopy=new asyncCopy();
//在典型用法中,将等待此调用
//在您的情况下,从异步方法进行此调用,并从UI线程进行调用
asyncCopy.EnqueueAndCopy(
新行动[]{
()=>CopyStuff(1),
()=>文案(2)
}
);
//循环以确认处理是异步的
对于(int i=0;i,如果您需要在处理其他副本时对副本进程进行异步排队,我建议使用生产者-消费者模式。请参阅
但简单的异步等待也适用于您的情况
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace stackoverflow {
class Program {
static void Main (string[] args) {
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}");
}
}
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)) {
//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);
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
使用系统线程;
命名空间堆栈溢出{
班级计划{
静态void Main(字符串[]参数){
var asyncCopy=new asyncCopy();
//在典型用法中,将等待此调用
//在您的情况下,从异步方法进行此调用,并从UI线程进行调用
asyncCopy.EnqueueAndCopy(
新行动[]{
()=>CopyStuff(1),
()=>文案(2)
}
);
//循环以确认处理是异步的
对于(int i=0;i CopyStuff(1),
()=>文案(2)
});
}
//复制过程模拟
静态void CopyStuff(int i)
{
睡眠(3000);
Show(string.Format(“复制的文件{0}”,i));
}
}
}
Hi Vishwa,谢谢您的帮助。但是我遇到了这个错误:“队列”不包含“TryDequeue”的定义,并且找不到接受“Queue”类型的第一个参数的扩展方法“TryDequeue”(是否缺少using指令或程序集引用?)您的参考资料中是否有使用System.Collections.Generic;
的。这有队列
数据结构是的,我有参考资料。我尝试了这个:经过修改。它可以工作,但在主UI线程上运行,因此用户没有其他控件可用。我已将代码更新为模拟复制进程。在调用复制进程以确认其异步运行后,包含for循环。不需要阻止集合
,因为我们不是从不同线程同时在队列中工作。使用操作
而不是方法调用程序
谢谢Vishwa。您的解决方案在控制台应用程序中工作,但在Windows窗体应用程序中使用时(MyQueue.TryDequeue(out var copyAction))
在上出现错误(是否缺少using指令或程序集引用?)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async Task CopyAsync(IEnumerable<Action> actionList)
{
foreach (var action in actionList)
{
await Task.Factory.StartNew(action);
}
}
private async void button2_Click(object sender, EventArgs e)
{
await CopyAsync(
new Action[]
{
() => CopyStuff(1),
() => CopyStuff(2)
});
}
//Copy process simulation
static void CopyStuff(int i)
{
Thread.Sleep(3000);
MessageBox.Show(string.Format("File Copied {0}", i));
}
}
}