Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# 下载100个文件后,线程似乎卡住了_C#_Multithreading_Http - Fatal编程技术网

C# 下载100个文件后,线程似乎卡住了

C# 下载100个文件后,线程似乎卡住了,c#,multithreading,http,C#,Multithreading,Http,我刚刚编写了一个下载管理器来并行下载多个文件。但是我对这个脚本有一个问题,我找不到答案。经过大量的文件(100个就可以了)。有时候一根线就是不能完成它的工作。它不会触发超时,也没有我放置的异常或控制台日志。当我检查需要下载所有文件的文件夹时,我看到那里有一个不完整的文件,应用程序正在使用它(我知道这一点,因为在关闭应用程序之前我无法删除该文件)。我希望有人能在我的剧本中看到这个问题 //Download complete delegate public delegate void Downloa

我刚刚编写了一个下载管理器来并行下载多个文件。但是我对这个脚本有一个问题,我找不到答案。经过大量的文件(100个就可以了)。有时候一根线就是不能完成它的工作。它不会触发超时,也没有我放置的异常或控制台日志。当我检查需要下载所有文件的文件夹时,我看到那里有一个不完整的文件,应用程序正在使用它(我知道这一点,因为在关闭应用程序之前我无法删除该文件)。我希望有人能在我的剧本中看到这个问题

//Download complete delegate
public delegate void DownloadCompleteHandler(DownloadableObject source, DownloadCompletedEventArgs e);

//Download complete event args
public class DownloadCompletedEventArgs : EventArgs
{
    private string EventInfo;
    public DownloadCompletedEventArgs(string text)
    {
        EventInfo = text;
    }
    public string GetInfo()
    {
        return EventInfo;
    }
}

class DownloadManager
{
    //Downloadcomplete Handler
    public event DownloadCompleteHandler DownloadComplete;

    //The amount of downloads that can run in parallel
    public int parallelDownloads = 1;

    //All the downloads in a list
    public List<DownloadableObject> downloads = new List<DownloadableObject>();

    public DownloadManager(int parallelDownloads = 1)
    {
        this.parallelDownloads = parallelDownloads;
    }

    //This adds a download to the list.
    public void addDownload(string url, string saveLocation)
    {
        DownloadableObject dl = new DownloadableObject() { url = url, saveLocation = saveLocation };
        downloads.Add(dl);
    }

    //This starts the parallel downloader
    public void startParallelDownloads()
    {
        for(int i = 0; i < parallelDownloads; i++)
        {
            startDownload();
        }
    }

    //This starts a single download Async
    private void startDownload()
    {
        //Check if the downloads list contains anything
        if(downloads.Any())
        {
            //Get the first download from the list and remove it so it doesn't get downloaded again.
            DownloadableObject currentDl = downloads[0];
            downloads.RemoveAt(0);

            //Setup a webrequest.
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(currentDl.url);
            webRequest.Method = "GET";
            webRequest.Timeout = 4000;
            currentDl.webRequest = webRequest;
            IAsyncResult result = webRequest.BeginGetResponse(new AsyncCallback(downloadResponse), currentDl);

            //This handles the timeout response
            ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(timeoutCallback), currentDl, currentDl.webRequest.Timeout, true);
        } else
        {
            //Called when a Thread is done downloading. This should be called when the download list is empty
            Console.WriteLine("THREAD DONE!");
        }
    }

    //This is the callback when a timeout occurs
    private void timeoutCallback(object state, bool timedOut)
    {
        if(timedOut)
        {
            //Get the timedout request
            HttpWebRequest request = ((DownloadableObject)state).webRequest;
            if(request != null)
            {
                Console.WriteLine("Too Bad!");
                //And abort it
                request.Abort();

                //Set the webrequest in the downloadable object to null and add it to the download list again so it will be downloaded again
                ((DownloadableObject)state).webRequest = null;
                downloads.Add(((DownloadableObject)state));
                //Refire the thread.
                startDownload();
            }
        }
    }

    private void downloadResponse(IAsyncResult asyncResult)
    {
        int received = 0;
        //Get the current download from the asyncResult.
        DownloadableObject currentDl = (DownloadableObject)asyncResult.AsyncState;

        try
        {
            using (HttpWebResponse webResponse = (HttpWebResponse)currentDl.webRequest.EndGetResponse(asyncResult))
            {
                byte[] buffer = new byte[1024];

                //Creates a file in the correct location.
                FileStream fileStream = File.OpenWrite(currentDl.saveLocation);
                using (Stream input = webResponse.GetResponseStream())
                {
                    //Write data to the buffer.
                    int size = input.Read(buffer, 0, buffer.Length);
                    while (size > 0)
                    {
                        fileStream.Write(buffer, 0, size);
                        received += size;

                        size = input.Read(buffer, 0, buffer.Length);
                    }
                }

                //Write data to the file and close it.
                fileStream.Flush();
                fileStream.Close();
                //Call the download complete event
                DownloadComplete(currentDl, new DownloadCompletedEventArgs("Download completed"));

                //refire the Thread again.
                startDownload();
            }
        }
        catch (WebException e)
        {

        }
    }
}

//A downloadable object.
public class DownloadableObject
{
    //Url to file to download
    public string url { get; set; }
    //Location where to save the file
    public string saveLocation { get; set; }
    //The webrequest that is assigned to this download. This will be null when the download list is filled.
    public HttpWebRequest webRequest { get; set; }
}
//下载完整的委托
公共委托void DownloadCompleteHandler(DownloadableObject源,DownloadCompletedEventArgs e);
//下载完整的事件参数
公共类下载CompletedEventArgs:EventArgs
{
私有字符串EventInfo;
公共下载CompletedEventArgs(字符串文本)
{
事件信息=文本;
}
公共字符串GetInfo()
{
返回事件信息;
}
}
类下载管理器
{
//下载完整处理程序
公共事件下载完成处理程序下载完成;
//可并行运行的下载量
公共int=1;
//列表中的所有下载
公共列表下载=新列表();
公共下载管理器(int parallelDownloads=1)
{
this.parallelldownloads=parallelldownloads;
}
//这会将下载添加到列表中。
public void addDownload(字符串url、字符串saveLocation)
{
DownloadableObject dl=新的DownloadableObject(){url=url,saveLocation=saveLocation};
下载.添加(dl);
}
//这将启动并行下载程序
public void startParallelDownloads()
{
for(int i=0;i0)
{
写入(缓冲区,0,大小);
接收+=大小;
size=input.Read(buffer,0,buffer.Length);
}
}
//将数据写入文件并关闭它。
Flush();
fileStream.Close();
//调用下载完成事件
下载完成(currentDl,新的下载完成事件参数(“下载完成”);
//把线再重新装一遍。
startDownload();
}
}
捕获(WebE例外)
{
}
}
}
//可下载的对象。
公共类可下载对象
{
//要下载的文件的Url
公共字符串url{get;set;}
//保存文件的位置
公共字符串保存位置{get;set;}
//分配给此下载的webrequest。填写下载列表时,此值将为空。
公共HttpWebRequest webRequest{get;set;}
}

Q:您是否连接了调试器并查看了“挂起”行的堆栈跟踪?问:是否只有一个线程挂起(其他线程是否完成其工作?)“几个线程”。。。还是整个程序挂起?它是随机的。我刚刚测试了2200个文件,有2个线程挂起。如何检查线程是在哪一行上