C# 多线程上传程序
我想上传巨大的文件(2到40 GB)到Azure Blob存储 首先,我成功地将每个文件分割成块(每个块=2MB)。 然后我一个接一个地上传区块,在成功上传每个区块后,我更新一个临时文件,以便在应用程序关闭时能够继续上传 现在我想让上传操作多线程化。 回顾了第三方物流之后,我不知道从哪里开始 从哪里开始第三方物流有什么指导吗C# 多线程上传程序,c#,multithreading,azure,task-parallel-library,C#,Multithreading,Azure,Task Parallel Library,我想上传巨大的文件(2到40 GB)到Azure Blob存储 首先,我成功地将每个文件分割成块(每个块=2MB)。 然后我一个接一个地上传区块,在成功上传每个区块后,我更新一个临时文件,以便在应用程序关闭时能够继续上传 现在我想让上传操作多线程化。 回顾了第三方物流之后,我不知道从哪里开始 从哪里开始第三方物流有什么指导吗 void Upload(int segmentId) { try { string blockId = GetBlockId(segment
void Upload(int segmentId)
{
try
{
string blockId = GetBlockId(segmentId);
var segment = GetSegment(FilePath, segmentId, SeqmentSize);
var md5Hash = CalcMd5Hash(segment);
var blob = new CloudBlockBlob(_link.Uri);
using (var memoryStream = new MemoryStream(segment))
{
blob.PutBlock(blockId, memoryStream, md5Hash);
}
SerializeStatus();
}
catch (Exception exception)
{
...
}
}
很久以前,我构建了类似的东西(虽然我使用异步方法而不是TPL),我想
上传具有可恢复功能的真正大的blob
。以下是我所做的:
NotStarted
、Successful
和Failed
NotStarted
的集合中获取x个项目。然后我并行处理这些块。我将区块id作为用户状态传递,以便在收到回拨时,根据上载状态相应地更新集合并序列化回数据using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UploadLargeBlob
{
class Program
{
static void Main(string[] args)
{
List<ChunkInformation> chunksToUpload = new List<ChunkInformation>();
CreateChunkCollection("MyVeryLargeFile", 2*1024*1024);
int numberOfParallelThreads = 8;
do
{
var chunksToProcess = chunksToUpload.Where(c => c.Status == ChunkStatus.NotStarted || c.Status == ChunkStatus.Failed).Take(numberOfParallelThreads);
if (chunksToProcess.Count() == 0)
{
break;
}
List<Task> tasks = new List<Task>();
try
{
foreach (var chunk in chunksToProcess)
{
tasks.Add(Task.Factory.StartNew(() =>
{
DoUpload(chunk);
}, chunk));
}
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException excep)
{
foreach (var task in tasks)
{
if (task.Exception != null)
{
ChunkInformation chunk = task.AsyncState as ChunkInformation;
chunk.Status = ChunkStatus.Failed;
//Now serialize the data.
}
}
}
}
while (true);
}
static void DoUpload(ChunkInformation chunk)
{
//Do the actual upload
//Update chunk status once chunk is uploaded
chunk.Status = ChunkStatus.Successful;
//Serialize the data.
}
static void CreateChunkCollection(string fileName, int chunkSize)
{
}
}
public class ChunkInformation
{
public string Id
{
get;
set;
}
public ChunkStatus Status
{
get;
set;
}
}
public enum ChunkStatus
{
NotStarted,
Successful,
Failed
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间UploadLargeBlob
{
班级计划
{
静态void Main(字符串[]参数)
{
List chunksToUpload=新建列表();
CreateChunkCollection(“MyVeryLargeFile”,2*1024*1024);
int numberOfParallelThreads=8;
做
{
var chunksToProcess=chunksToUpload.Where(c=>c.Status==ChunkStatus.NotStarted | | c.Status==ChunkStatus.Failed);
if(chunksToProcess.Count()==0)
{
打破
}
列表任务=新列表();
尝试
{
foreach(chunksToProcess中的var chunk)
{
tasks.Add(Task.Factory.StartNew(()=>
{
双倍体;
}组块);
}
Task.WaitAll(tasks.ToArray());
}
捕获(聚合异常例外)
{
foreach(任务中的var任务)
{
if(task.Exception!=null)
{
ChunkInformation chunk=task.AsyncState作为ChunkInformation;
chunk.Status=ChunkStatus.Failed;
//现在序列化数据。
}
}
}
}
虽然(正确);
}
静态void双重加载(ChunkInformation chunk)
{
//进行实际上传
//上传区块后更新区块状态
chunk.Status=ChunkStatus.Successful;
//序列化数据。
}
静态void CreateChunkCollection(字符串文件名,int chunkSize)
{
}
}
公共类信息
{
公共字符串Id
{
得到;
设置
}
公共地位
{
得到;
设置
}
}
公共枚举块状态
{
没有开始,
成功的
失败
}
}
提供一些代码,请告诉我您可用的上传带宽是多少???@RobertoBonini~8 Mbit如果第3段在第2段之前上传,会由服务器上的blockId
来处理吗?@Belogix我有一个方法来处理段的顺序。这正是我所做的。我的问题是如何实现多线程?这是多线程的。Task.Factory.StartNew将新工作项添加到TPL的线程池工作项队列中。