Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程方法的同步行为_C#_Multithreading_Listview_Arraylist - Fatal编程技术网

C# 多线程方法的同步行为

C# 多线程方法的同步行为,c#,multithreading,listview,arraylist,C#,Multithreading,Listview,Arraylist,在这方面花了很长时间后,我无法用这种方法成功地实现多线程。我真的很感谢你的帮助 我有一个列表视图,其中第一列有我们稍后在其他方法中需要的URL。“秒”列用于显示结果 我创建了两个带有url的arraylist,并将它们(带有arraylist的url)发送到该方法,然后在该方法中,通过一个httpwebrequest,我从每个url获取页面标题 所以问题是,当我尝试启动5个线程时,它的工作原理如下: (U:url,R:result) u1=r1(因此,我必须将u1的结果作为r1..) 但我觉得:

在这方面花了很长时间后,我无法用这种方法成功地实现多线程。我真的很感谢你的帮助

我有一个
列表视图
,其中第一列有我们稍后在其他方法中需要的URL。“秒”列用于显示结果

我创建了两个带有url的
arraylist
,并将它们(带有arraylist的url)发送到该方法,然后在该方法中,通过一个
httpwebrequest
,我从每个url获取页面标题

所以问题是,当我尝试启动
5个线程时,它的工作原理如下:

(U:url,R:result)

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
关键字,但随后我丢失了
多线程
。它的工作原理与我所期望的一样,只是一个接一个。不要同时触发5个不同的线程,并等待完成线程1以移动到下一个线程

///主类///

/* 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();
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关键字,顺便说一下,在这个例子中,激发了5个线程,但它等待第一个线程的结束。。。

这就是我想做的。。。

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

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”)。在listview的所有项目上运行一个循环,以查找FileDownloader的项目。为什么FileDownloader对他的项目一无所知?如果FileDownloader知道他的项目,那么您就不需要这个周期。您将在FileDownloader和他的项目之间有一个明确的链接。

“PageTitlerResult=pageTitle;”-什么是“PageTitlerResult”,“pageTitle”?它们的定义和用途在哪里?@AlexanderKiselev我刚刚编辑了这部分。。这只是html敏捷性包的工作,不管有没有它,线程问题都不会改变,这就是为什么我删除了这一部分以稍微清除代码。我在代码中找不到将字符串插入ListView列的位置:item.Subitems[1],其中是url,item.Subitems[2],结果在哪里,如果我正确理解了您的帖子。@AlexanderKiselev感谢您的时间alexander,我刚刚添加了用于多线程的其他必要方法。在方法PageRankReturns()中,尝试“if(f.Equals(item.Tag))”而不是“if(item.Tag==f)”。结果相同。我认为最好检查所有代码。从这里开始:。对于我所做的改变,你可以从上面看到。好吧,我想我会继续并行,我仍然无法解决这个问题@亚历山大·基塞列夫