多线程方法

时间:2015-09-30 12:27:25

标签: c# multithreading listview arraylist

经过长时间的工作,我使用此方法multi-threading无法取得任何成功。我非常感谢你的帮助。

我有listview,其中第一列包含我们稍后将在其他方法中使用的网址。秒列用于结果。

我正在创建两个带有网址的ArrayLists并将它们(带有arraylist的网址)发送到方法,然后在方法中,使用httpwebrequest,我从每个网址获取网页标题

所以问题是当我尝试解雇5 threads时,它就像:

(U:url,R:结果)

u1 = r1(所以,我必须得到u1的结果为r1 ..)

但我变得像:

u1 = r1,u2 = r1,u3(或4)= r1,u4 = r1,u5 = r2(或3,4)

但我期待的是: u1 = r1,u2 = r2,u3 = r3,u4 = r4 ......

有关更好的说明,请查看下面的图片

然后我尝试将Lock关键字与私有对象一起使用,但之后我丢失了multi-threading。它的工作方式除了我之外一个接一个。不要同时触发5个不同的线程,并等待完成线程1移动到下一个线程。

/// Main Class ///

/* A store of all created threads. */
ArrayList _threads = new ArrayList();
/* A store of all FileDownloader objects. */
ArrayList _instances = new ArrayList();
private int _activeDownloadCount = 0;
object _lockObject = new object();

按钮:

_instances = new ArrayList();
_threads = new ArrayList();
_activeDownloadCount = 0;

FileDownloader download = null;
foreach (ListViewItem item in listviewUrl.Items)
{               
  item.SubItems[9].Text = "Not started";        

    download = new FileDownloader(item.SubItems[0].Text);               
    item.Tag = download;                
    try
    {
       ThreadStart tsDelegate = new ThreadStart(download.Download);
       download.DownloadStarting += new FileDownloader._delDownloadStarting(download_DownloadStarting);
       download.DownloadCompleted += new FileDownloader._delDownloadCompleted(download_DownloadCompleted);

       Thread t = new Thread(tsDelegate);
       t.Name = item.SubItems[0].Text;
       _threads.Add(t);
       _instances.Add(download); 
    }
    catch
    {

        item.SubItems[9].Text = "Error";
    }
}
StartDownload();

开始下载方法:

int j = 0;
int limit = int.Parse(numThreadSearch.Text);
int iCount = 0;
lock (_lockObject)
{
    iCount = _instances.Count;
}
if (iCount != 0)
{
    foreach (Thread thread in _threads)
    {
        FileDownloader file = ((FileDownloader)_instances[j]);
        if (file._IsStarted == false)
        {
            lock (_lockObject)
            {
                thread.Start();

                Console.WriteLine(_activeDownloadCount);
                _activeDownloadCount++;
            }
        }
        if (_activeDownloadCount == limit)
        {
            break;
        }
        j++;
    }
}
else
{
    /* If all the files have downloaded, we will do something here.
}

方法完成时:

 void download_DownloadCompleted(FileDownloader thread, bool isSuccess)
        {

            lock (_lockObject)
            {
                _activeDownloadCount--;

            }

            PageRankReturns(FileDownloader._PageRankReturn, thread);
            RemoveFromInternalPool(thread);
            StartDownload();

        }


         delegate void delSetStatus(string Status, FileDownloader f);

     private void PageRankReturns(string Status, FileDownloader f)
            {
                if (listviewUrl.InvokeRequired)
                {
                    delSetStatus s = new delSetStatus(PageRankReturns);
                    this.Invoke(s, new object[] { Status, f });
                }
                else
                {
                    foreach (ListViewItem item in listviewUrl.Items)
                    {
                        if (item.Tag == f)
                        {
                            /* Use locking to synchronise across mutilple thread calls. */
                            lock (_lockObject)
                            {
                                item.SubItems[2].Text = Status;

                            }
                            break;
                        }
                    }
                }
            }



 private void RemoveFromInternalPool(FileDownloader thread)
        {
            int i = 0;
            foreach (FileDownloader f in _instances)
            {
                if (f == thread)
                {
                    /* If the file has downloaded, remove it from our pool. */
                    lock (_lockObject)
                    {
                        _threads.Remove(_threads[i]);
                        _instances.Remove(f);
                        break;
                    }
                }
                i++;
            }
        }

///第二类///

#region  Fields

private string _DocumentUrl = string.Empty;
private string _DirectoryPath = string.Empty;
public bool _IsDownloading = false;
public bool _IsDownloadSuccessful = false;

public bool _IsStarted = false;

#endregion

#region Delegates
public delegate void _delDownloadStarting(FileDownloader thread);
public delegate void _delDownloadCompleted(FileDownloader thread, bool isSuccess);
public delegate void _delDownloadCWorking(FileDownloader thread);

#endregion

#region Events
public event _delDownloadStarting DownloadStarting;
public event _delDownloadCompleted DownloadCompleted;

protected static readonly object locker = new object();
public static string pageTitleResult= string.Empty;

public static string _pageTitleResult
{
    get { return pageTitleResult; }
}

public FileDownloader(string documentUrl)
{
    _DocumentUrl = documentUrl;
}

//下载方法//

public void Download()
{
    _IsStarted = true;
    DownloadStarting(this);            
    _IsDownloading = true;
    _IsDownloadSuccessful = false;

    // with lock keyword it works one by one//
    //without lock or monitor.enter keyword then it works as i tried explain above u1 = r1, u2 = r1, ur3 = r1, u4=r3 etc...

    try
    {
        string pageHtml = getHtml(_DocumentUrl);
        HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();

        //html agibility works with returned string from gethtml...
      // string pageTitle = html agibility work result, it's string...
       pageTitleResult = pageTitle 

        _IsDownloadSuccessful = true;
        _IsDownloading = false;
        /* raise a download completed event. */
        DownloadCompleted(this, _IsDownloadSuccessful);
    }
    catch
    {
        _IsDownloadSuccessful = false;
    }
   Thread.Sleep(10);
}

锁定对象:

protected static readonly object locker = new object();

好吧,我刚刚在excel中做了一个例子来说明它是如何工作的......

这是没有Lock关键字的返回: Without Lock keyword for method

这是使用lock关键字,顺便说一下,在这个例子中,触发了5个线程,但它等待第一个结束... enter image description here

这就是我想要做的...... enter image description here

1 个答案:

答案 0 :(得分:0)

我认为,这个方法存在一个问题:

private void PageRankReturns(string Status, FileDownloader f)
{
            if (listviewUrl.InvokeRequired)
            {
                delSetStatus s = new delSetStatus(PageRankReturns);
                this.Invoke(s, new object[] { Status, f });
            }
            else
            {
                foreach (ListViewItem item in listviewUrl.Items)
                {
                    if (item.Tag == f)
                    {
                        /* Use locking to synchronise across mutilple thread calls. */
                        lock (_lockObject)
                        {
                            item.SubItems[2].Text = Status;

                        }
                        break;
                    }
                }
            }
}

您必须更改应用程序的结构。 请参阅上面的方法(“PageRankReturns”)。您在列表视图的所有项目上运行一个循环,以查找FileDownloader的项目。为什么FileDownloader对他的项目一无所知?如果FileDownloader知道他的项目,那么你将不需要这个循环。并且你将在FileDownloader和他的Item之间有一个明确的链接。