gpt4 book ai didi

c# - 当其中一个下载线程终止时解锁 FIleStream

转载 作者:行者123 更新时间:2023-11-30 14:41:52 27 4
gpt4 key购买 nike

我通过例如下载文件5 个线程。当其中一个线程完成下载文件部分时 - 它被中止,但所有其余线程都有 ThreadState = WaitSleepJoin 并且显然停止下载。如何解决?

while ((bytesSize = responseStream.Read(Buffer, 0, Buffer.Length)) > 0)
{
lock(fileStream)
{
fileStream.Write(Buffer, 0, bytesSize);

if (DownloadedBytesCount >= EndPosition - StartPosition)
{
downThread.Abort();
break;
}
else DownloadedBytesCount += bytesSize;
}
}

我想 fileStream 在 downThread.Abort() 之后仍然被阻塞。我以为中断会解锁文件流,但事实并非如此。那么如何解锁该文件呢?

这里有更多信息:

我有一个类“ThreadFileManager”:

public class ThreadFileManager
{
public ThreadContent[] threads;
protected static FileStream fileStream { get; set; }

public ThreadFileManager(string fileUrl, string LocalPath, int ThreadCount, int bufferLength, ProgressBar progressBarReference)
{
if (File.Exists(LocalPath))
fileStream = new FileStream(LocalPath, FileMode.Append, FileAccess.Write);
else fileStream = new FileStream(LocalPath, FileMode.Create, FileAccess.Write);

CreateThreads(fileUrl, ThreadCount, bufferLength); //create threads and start downloading
}

private void CreateThreads(string fileUrl, int ThreadCount, int bufferLength)
{
webRequest = (HttpWebRequest)WebRequest.Create(fileUrl);

webRequest.Credentials = CredentialCache.DefaultCredentials;

webResponse = (HttpWebResponse)webRequest.GetResponse();
responseStream = webResponse.GetResponseStream();

//calculate the total bytes count to download per one thread
long part = webResponse.ContentLength / ThreadCount;
fileLength = webResponse.ContentLength;

this.threads = new ThreadContent[ThreadCount];

ThreadContent thr_cn = new ThreadContent(bufferLength, fileUrl);
thr_cn.StartPosition = 0;
thr_cn.EndPosition = part;

threads[0] = thr_cn;

for (int i = 1; i < ThreadCount; i++)
{
thr_cn = new ThreadContent(bufferLength, fileUrl);

thr_cn.StartPosition = (i * part) + 1;
thr_cn.EndPosition = (i + 1) * part;
this.threads[i] = thr_cn;
}
}
}

public class ThreadContent : ThreadFileManager
{
public long StartPosition { get; set; } //the Begining position of the downloading file
public long EndPosition { get; set; } //the End position of the downloading file
public byte[] Buffer { get; set; }

HttpWebRequest webRequest { get; set; }
HttpWebResponse webResponse { get; set; }
long BufferLength { get; set; }
long DownloadedBytesCount { get; set; }

Thread downThread;
string FileURL { get; set; }

public ThreadContent(int bufferLength, string url)
{
Buffer = new byte[bufferLength];
downThread = new Thread(new ThreadStart(Download));
FileURL = url;
}

public void Download()
{
int bytesSize = 0;
webRequest = (HttpWebRequest)WebRequest.Create(FileURL);

webRequest.Credentials = CredentialCache.DefaultCredentials;

webResponse = (HttpWebResponse)webRequest.GetResponse();
responseStream = webResponse.GetResponseStream();

webRequest.AddRange(StartPosition, EndPosition);

while ((bytesSize = responseStream.Read(Buffer, 0, Buffer.Length)) > 0)
{
lock (fileStream)
{
fileStream.Write(Buffer, 0, bytesSize);
base.UpdateProgress(bytesSize);
}

if (DownloadedBytesCount >= EndPosition - StartPosition)
{
downThread.Abort();
break;
}
else DownloadedBytesCount += bytesSize;
}
}

最佳答案

一般来说,您的方法是不正确的,因为您不应该通过调用 Abort() 来结束您的线程。这最终会引发异常。我尝试的方法是只允许线程返回而不是中止。您可以通过传递关于何时返回的线程信息来做到这一点。另一种方法(可能更好)是使用 AutoResetEvent,并在您希望每个线程结束时使用 Set()。线程内部的代码应该是这样的:

AutoResetEvent e = new AutoResetEvent( false);
while( !e.WaitOne( 0)) {
// your code here
}

您似乎希望这 5 个线程共享有关下载状态的信息,即每个线程已下载了多少字节。如果你想要实时更新(我假设),你可以将对计数的引用传递给每个线程,并确保每个线程使用锁来保护对该变量的访问。或者你可以让它每 1K 或更多更新一次字节数,这样你就不会锁定和解锁一堆。

如果你有一个管理这些多个下载线程的工作线程,那么你可以启动每个线程,然后从“主”工作线程(即不是主线程本身,否则你的 GUI 将阻塞)使用 EndInvoke 来确保每个线程已经正常结束。或者您可以使用 AsyncCallback,它会在每个线程完成时被调用。在 AsyncCallback 中,您可以调用 EndInvoke。

关于c# - 当其中一个下载线程终止时解锁 FIleStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3645955/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com