1

.NET 2.0、C#、および VS2010 を使用した WinformApplication と ConsoleApplication の 2 つのプログラムがあります。

2 つのプログラムは、backgroundworker と EventWaitHandle のタスクが同じです。

  1. BGW の作成
  2. 仕事する
  3. RunWorkerCompleted { .. event.Set(); ..}
  4. 待機 event.waitone()

コンソール アプリは問題なく動作します。ただし、フォーム アプリは機能しません。ここに完全なコードがあります。試してみて、何が問題なのか教えてください。

WinFormApplication コードは次のとおりです。

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        ProducerConsumerQueue[] q = new ProducerConsumerQueue[51];

        public Form1()
        {
            InitializeComponent();
            SetMinThreads();

            for (int i = 0; i < 51; i++)
                q[i] = new ProducerConsumerQueue(i);

            ReadyToWork();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void SetMinThreads()
        {
            int workerT, portT;
            int minRequire = 51 + 5;

            ThreadPool.GetMaxThreads(out workerT, out portT);
            ThreadPool.GetMinThreads(out workerT, out portT);

            if (workerT < minRequire)
            {
                int inc = minRequire - workerT;
                workerT += inc;
            }

            ThreadPool.SetMinThreads(workerT, portT);
            Console.WriteLine(string.Format("Min: worker - {0}, port - {1}", workerT, portT));
        }

        private void ReadyToWork()
        {
            for (int i = 0; i < 51; i++)
                q[i].ReadParamFromController(true);

            for (int i = 0; i < 51; i++)
                q[i].ReadParamFromController(false);
        }
    }

    class ProducerConsumerQueue
    {
        EventWaitHandle _wh = new ManualResetEvent(false);
        int _id;
        public ProducerConsumerQueue(int id)
        {
            _id = id;
        }

        public void ReadParamFromController(bool isStart)
        {
            if (isStart)
            {
                {
                    _wh = new ManualResetEvent(false);

                    BackgroundWorker bwReadFromController = new BackgroundWorker();
                    bwReadFromController.WorkerSupportsCancellation = true;
                    bwReadFromController.DoWork += new DoWorkEventHandler(bwReadFromController_DoWork);
                    bwReadFromController.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwReadFromController_RunWorkerCompleted);
                    bwReadFromController.RunWorkerAsync();
                }
            }
            else
            {
                _wh.WaitOne();
            }
        }

        private void bwReadFromController_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                Console.WriteLine("Cancelled task: ");
            }
            else if (!(e.Error == null))
            {
                Console.WriteLine("Error task: ");
            }
            else
            {
                Console.WriteLine("Performing Done: " + _id);
            }

            _wh.Set();

            ((BackgroundWorker)sender).Dispose();
            GC.Collect();
        }

        private void bwReadFromController_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            const int readFromControllerCount = 25;

            for (int i = 0; i < readFromControllerCount; i++)
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Do something
                    System.Threading.Thread.Sleep(10);
                }
            }
        }
    }
}

ConsoleApplication コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
        {
            DateTime dt = DateTime.Now;
            Console.WriteLine(string.Format("start {0}", dt.ToString()));

            SetMinThreads();

            ProducerConsumerQueue[] q = new ProducerConsumerQueue[51];
            for (int i = 0; i < 51; i++)
                q[i] = new ProducerConsumerQueue(i);

            for (int i = 0; i < 51; i++)
                q[i].ReadParamFromController(true);// = new ProducerConsumerQueue();

            dt = DateTime.Now;
            Console.WriteLine(string.Format("Read Start {0}", dt.ToString()));

            for (int i = 0; i < 51; i++)
                q[i].ReadParamFromController(false);// = new ProducerConsumerQueue();

            Console.WriteLine();

            dt = DateTime.Now;
            Console.WriteLine(string.Format("Workers complete!  {0}", dt.ToString()));

            // Exiting the using statement calls q's Dispose method, which
            // enqueues a null task and waits until the consumer finishes.

            Console.ReadLine();
        }

        static private void SetMinThreads()
        {
            int workerT, portT;
            int minRequire = 51 + 5;

            ThreadPool.GetMaxThreads(out workerT, out portT);
            ThreadPool.GetMinThreads(out workerT, out portT);

            if (workerT < minRequire)
            {
                int inc = minRequire - workerT;
                workerT += inc;
            }

            ThreadPool.SetMinThreads(workerT, portT);
            Console.WriteLine(string.Format("Min: worker - {0}, port - {1}", workerT, portT));
        }
    }

    class ProducerConsumerQueue
    {
        EventWaitHandle _wh = new ManualResetEvent(false);
        int _id;
        public ProducerConsumerQueue(int id)
        {
            _id = id;
        }

        public void ReadParamFromController(bool isStart)
        {
            if (isStart)
            {
                {
                    _wh = new ManualResetEvent(false);

                    BackgroundWorker bwReadFromController = new BackgroundWorker();
                    bwReadFromController.WorkerSupportsCancellation = true;
                    bwReadFromController.DoWork += new DoWorkEventHandler(bwReadFromController_DoWork);
                    bwReadFromController.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwReadFromController_RunWorkerCompleted);
                    bwReadFromController.RunWorkerAsync();
                }
            }
            else
            {
                _wh.WaitOne();
            }
        }

        private void bwReadFromController_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                Console.WriteLine("Cancelled task: ");
            }
            else if (!(e.Error == null))
            {
                Console.WriteLine("Error task: ");
            }
            else
            {
                Console.WriteLine("Performing Done: " + _id);
            }

            _wh.Set();

            ((BackgroundWorker)sender).Dispose();
            GC.Collect();
        }

        private void bwReadFromController_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            const int readFromControllerCount = 1;

            for (int i = 0; i < readFromControllerCount; i++)
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    //Console.WriteLine("Performing tasks: " + i);
                    System.Threading.Thread.Sleep(10);
                }
            }
        }
    }
}
4

0 に答える 0