使用C#Queue<;MethodInvoker>;

使用C#Queue<;MethodInvoker>;,c#,queue,filecopy,C#,Queue,Filecopy,我正在尝试创建一个文件复制应用程序。我有一个工作背景的人在做这项工作,到目前为止效果很好。如何工作,我有一个表单,源和目标文件夹字段和一个复制按钮。复制按钮使用BackgroundWorker触发复制操作。Progressbar得到更新等。现在我需要实现一个队列类型的操作。我需要添加其他源和目标复制操作,并将其添加到队列中。我尝试使用以下方法: Queue<MethodInvoker> MyQueue = new Queue<MethodInvoker>();

我正在尝试创建一个文件复制应用程序。我有一个工作背景的人在做这项工作,到目前为止效果很好。如何工作,我有一个表单,源和目标文件夹字段和一个复制按钮。复制按钮使用BackgroundWorker触发复制操作。Progressbar得到更新等。现在我需要实现一个队列类型的操作。我需要添加其他源和目标复制操作,并将其添加到队列中。我尝试使用以下方法:

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));
    }
}
}