0

Form1 で、_busy 変数を削除/削除しました。Form1トップで私がした:

BackgroundWebCrawling bgwc;

次に、button4 の一時停止クリック イベントで、次のようにしました。

private void button4_Click(object sender, EventArgs e)
{
    bgwc.PauseWorker();
    label6.Text = "Process Paused";
    button5.Enabled = true;
    button4.Enabled = false;
}

button5 クリック イベント ボタンで、次のことを行いました。

private void button5_Click(object sender, EventArgs e)
{
    bgwc.ContinueWorker();
    label6.Text = "Process Resumed";
    button4.Enabled = true;
    button5.Enabled = false;
}

そして、キャンセルボタンのクリックイベント:

private void button3_Click(object sender, EventArgs e)
{
    bgwc.CancelWorker();
    cancel = true;
}

次に、キャンセルが true かどうかを Form1 の完了イベントでチェックしています。

if (cancel == true)
{
    label6.Text = "Process Cancelled";
}
else
{
    label6.Text = "Process Completed";
}

BackgroundWebCrawling クラスは次のようになります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HtmlAgilityPack;
using System.Net;
using System.Windows.Forms;
using System.ComponentModel;
using System.Threading;

namespace GatherLinks
{
    class BackgroundWebCrawling
    {
        public string f;
        int counter = 0;
        List<string> WebSitesToCrawl;
        int MaxSimultaneousThreads;
        public BackgroundWorker mainBackGroundWorker;
        BackgroundWorker secondryBackGroundWorker;
        WebcrawlerConfiguration webcrawlerCFG;
        List<WebCrawler> webcrawlers;
        int maxlevels;
        public event EventHandler<BackgroundWebCrawlingProgressEventHandler> ProgressEvent;
        ManualResetEvent _busy = new ManualResetEvent(true);

        public BackgroundWebCrawling()
        {
            webcrawlers = new List<WebCrawler>();
            mainBackGroundWorker = new BackgroundWorker();
            mainBackGroundWorker.WorkerSupportsCancellation = true;
            mainBackGroundWorker.DoWork += mainBackGroundWorker_DoWork;
        }

        private void mainBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            for (int i = 0; i < WebSitesToCrawl.Count; i++)
            {
                _busy.WaitOne();
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                while (counter >= MaxSimultaneousThreads)
                {
                    Thread.Sleep(10);
                }

                WebCrawler wc = new WebCrawler(webcrawlerCFG);
                webcrawlers.Add(wc);
                counter++;
                secondryBackGroundWorker = new BackgroundWorker();
                secondryBackGroundWorker.DoWork += secondryBackGroundWorker_DoWork;
                object[] args = new object[] { wc, WebSitesToCrawl[i] };
                secondryBackGroundWorker.RunWorkerAsync(args);
            }
            while (counter > 0)
            {
                Thread.Sleep(10);
            }
        }

        private void secondryBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            object[] args = (object[])e.Argument;
            WebCrawler wc = (WebCrawler)args[0];
            string mainUrl = (string)args[1];
            wc.ProgressEvent += new EventHandler<WebCrawler.WebCrawlerProgressEventHandler>(x_ProgressEvent);
            wc.webCrawler(mainUrl, maxlevels);

            counter--;
        }

        public void Start(List<string> sitestocrawl, int threadsNumber, int maxlevels, WebcrawlerConfiguration wccfg)
        {
            this.maxlevels = maxlevels;
            webcrawlerCFG = wccfg;
            WebSitesToCrawl = sitestocrawl;
            MaxSimultaneousThreads = threadsNumber;
            mainBackGroundWorker.RunWorkerAsync();
        }

        private void x_ProgressEvent(object sender, WebCrawler.WebCrawlerProgressEventHandler e)
        {
            // OK .. so now you get the data here in e
            // and here you should call the event to form1
            Object[] temp_arr = new Object[8];
            temp_arr[0] = e.csFiles;
            temp_arr[1] = e.mainUrl;
            temp_arr[2] = e.levels;
            temp_arr[3] = e.currentCrawlingSite;
            temp_arr[4] = e.sitesToCrawl;
            temp_arr[5] = e.done;
            temp_arr[6] = e.failedUrls;
            temp_arr[7] = e.failed;
            OnProgressEvent(temp_arr); /// Send the data + additional data from this class to Form1..
                                       ///
            /*
             * temp_arr[0] = csFiles;
                temp_arr[1] = mainUrl;
                temp_arr[2] = levels;
                temp_arr[3] = currentCrawlingSite;
                temp_arr[4] = sitesToCrawl;*/
        }

        private void GetLists(List<string> allWebSites)
        {

        }

        public class BackgroundWebCrawlingProgressEventHandler : EventArgs
        {
            public List<string> csFiles { get; set; }
            public string mainUrl { get; set; }
            public int levels { get; set; }
            public List<string> currentCrawlingSite { get; set; }
            public List<string> sitesToCrawl { get; set; }
            public bool done { get; set; }
            public int failedUrls { get; set; }
            public bool failed { get; set; }
        }

        protected void OnProgressEvent(Object[] some_params) // Probably you need to some vars here to...
        {
            // some_params to put in evenetArgs..
            if (ProgressEvent != null)
                ProgressEvent(this,
                    new BackgroundWebCrawlingProgressEventHandler()
                    {
                        csFiles = (List<string>)some_params[0],
                        mainUrl = (string)some_params[1],
                        levels = (int)some_params[2],
                        currentCrawlingSite = (List<string>)some_params[3],
                        sitesToCrawl = (List<string>)some_params[4],
                        done = (bool)some_params[5],
                        failedUrls = (int)some_params[6],
                        failed = (bool)some_params[7]
                    });
        }

        public void PauseWorker()
        {
            if (mainBackGroundWorker.IsBusy)
            {
                _busy.Reset();
            }
        }

        public void ContinueWorker()
        {
            _busy.Set();
        }

        public void CancelWorker()
        {
            ContinueWorker();
            mainBackGroundWorker.CancelAsync();
        }

    }
}

そこで、一時停止、継続、キャンセルのメソッドを追加しました。dowork イベントでは、すべてを変更したり、追加したりしました。

しかし、ボタンをクリックしても効果はありません。一時停止しない、続行しない、キャンセルしない。何もない。

4

1 に答える 1

3

メソッドで_busyステータスを確認することはありません。mainBackGroundWorker_DoWork

for (int i = 0; i < WebSitesToCrawl.Count; i++)
{
    _busy.WaitOne();
    //...
}

ManualResetEvent _busyまた、クラス内で BackgroundWorker を使用する必要があります

ManualResetEvent _busy = new ManualResetEvent(true);
public BackgroundWorker mainBackGroundWorker;

public void PauseWorker()
{
   if(mainBackGroundWorker.IsBusy)
   {
        _busy.Reset(); 
   }
}

public void ContinueWorker()
{
    _busy.Set();
}

とでForm1

private void button4_Click(object sender, EventArgs e)
{
    bgwc.PauseWorker();
    //...
}

private void button5_Click(object sender, EventArgs e)
{
    bgwc.ContinueWorker();
    //...
}

BackgroundWorker をキャンセルするには、CancellationPendingプロパティとCancelAsyncメソッドを使用できます。注: 最初にワーカーの一時停止を解除する必要があります。

public void CancelWorker()
{
   ContinueWorker();
   mainBackGroundWorker.CancelAsync();
}

private void mainBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    for (int i = 0; i < WebSitesToCrawl.Count; i++)
    {
        _busy.WaitOne();
         if ((worker.CancellationPending == true))
         {
             e.Cancel = true;
             break;
         }
         //...
    }  
}

これで問題が解決しない場合は、mainBackGroundWorkerコードとsecondryBackGroundWorker.

  1. このコードは mainBackGroundWorker のみを一時停止しますが、secondryBackGroundWorkers は一時停止しません。キャンセルも同様。メインワーカーがキャンセルされた場合は? すべてのセカンダリ ワーカーがジョブを完了するのを待ちます。また、メインワーカーを一時停止すると?セカンダリ ワーカーから新しい結果を受け取ることができます。

  2. エラーを処理しません。2 番目のワーカーで例外が発生した場合、それに関する通知はなく、メインのワーカーは決して停止しないため、停止することcounterはありません0

  3. 別の問題がある可能性があります。魔女がこの動作を引き起こす可能性があります。

于 2013-09-10T22:38:02.210 に答える