C# 处理API的并行POST

C# 处理API的并行POST,c#,rest,parallel-processing,task,C#,Rest,Parallel Processing,Task,我有一个API Post方法,它接受一个字符串,表示API转换为PDF的word文档中的Bae64字节字符串。我的测试客户机向要转换的API发送多个文档,每个文档都有自己的任务。问题在于并发性和写入文件。由于调用是并行的,因此我最终使用了一个文件。我尝试了很多不同的方法来阻止转换过程,直到文档被转换,但都没有成功。如果只是一个文件被转换,那么一切都可以正常工作,但是只要是2个或更多,问题就会出现。有谁能给我指引解决这个问题的正确方向吗 API: [HttpPost] 公共异步任务Post([Fr

我有一个API Post方法,它接受一个字符串,表示API转换为PDF的word文档中的Bae64字节字符串。我的测试客户机向要转换的API发送多个文档,每个文档都有自己的任务。问题在于并发性和写入文件。由于调用是并行的,因此我最终使用了一个文件。我尝试了很多不同的方法来阻止转换过程,直到文档被转换,但都没有成功。如果只是一个文件被转换,那么一切都可以正常工作,但是只要是2个或更多,问题就会出现。有谁能给我指引解决这个问题的正确方向吗

API:

[HttpPost]
公共异步任务Post([FromBody]字符串请求)
{
var response=新的SimpleResponse();
Task t=Task.Factory.StartNew(异步()=>
{
尝试
{
Converter convert=新转换器();
var result=await convert.CovertDocToPDF(请求,WebConfiguration Manager.AppSettings[“tempDocPath”],WebConfiguration Manager.AppSettings[“tempdfpath”]);
响应。结果=结果;
回答:成功=正确;
}
捕获(例外情况除外)
{
响应。异常=ex;
回答:成功=错误;
response.Errors=新列表();
Add(string.Format(“{0},{1}”,例如Message,例如InnerException?.Message??”);
}
});
t、 等待();
返回响应;
}
转换码

        public Task<string> CovertDocToPDF(string blob, string tempDocPath, string tempPdfPath)
        {
            try
            {
                // Convert blob back to bytes
                byte[] bte = Convert.FromBase64String(blob);

                // Process and return blob
                return Process(bte, tempDocPath, tempPdfPath);
            }
            catch (Exception Ex)
            {
                throw Ex;
            }            
        }

        private async Task<string> Process(byte[] bytes, string tempDocPath, string tempPdfPath)
        {
            try
            {
                string rs = RandomString(16, true);
                tempDocPath = tempDocPath + rs + ".docx";
                tempPdfPath = tempPdfPath + rs + ".pdf";

                // This is where the problem happens with concurrent calls. I added
                // the try catch when the file is in use to generate a new
                // filename but the error still happens.
                try
                {
                    // Create a temp file
                    File.WriteAllBytes(tempDocPath, bytes);
                }
                catch (Exception Ex)
                {
                    rs = RandomString(16, true);
                    tempDocPath = tempDocPath + rs + ".docx";
                    tempPdfPath = tempPdfPath + rs + ".pdf";
                    File.WriteAllBytes(tempDocPath, bytes);
                }

                word.Application app = new word.Application();
                word.Document doc = app.Documents.Open(tempDocPath);
                doc.SaveAs2(tempPdfPath, word.WdSaveFormat.wdFormatPDF);

                doc.Close();
                app.Quit(); // Clean up the word instance.

                // Need the bytes to return the blob
                byte[] pdfFileBytes = File.ReadAllBytes(tempPdfPath);

                // Delete temp files
                File.Delete(tempDocPath);
                File.Delete(tempPdfPath);

                // return blob
                return Convert.ToBase64String(pdfFileBytes);
            }
            catch (Exception Ex)
            {
                throw Ex;
            }
        }
public Task CovertDocToPDF(字符串blob、字符串tempDocPath、字符串tempdfpath)
{
尝试
{
//将blob转换回字节
字节[]bte=Convert.FromBase64String(blob);
//处理和返回blob
返回流程(bte、tempDocPath、tempdfpath);
}
捕获(例外情况除外)
{
掷骰子;
}            
}
专用异步任务进程(字节[]字节,字符串tempDocPath,字符串tempdfpath)
{
尝试
{
字符串rs=随机字符串(16,真);
tempDocPath=tempDocPath+rs+“.docx”;
tempPdfPath=tempPdfPath+rs+“.pdf”;
//这就是并发调用的问题所在
//文件用于生成新文件时的try catch
//但错误仍然发生。
尝试
{
//创建一个临时文件
writealBytes(tempDocPath,字节);
}
捕获(例外情况除外)
{
rs=随机字符串(16,真);
tempDocPath=tempDocPath+rs+“.docx”;
tempPdfPath=tempPdfPath+rs+“.pdf”;
writealBytes(tempDocPath,字节);
}
word.Application app=新的word.Application();
word.Document doc=app.Documents.Open(tempDocPath);
doc.SaveAs2(tempPdfPath,word.WdSaveFormat.wdFormatPDF);
doc.Close();
app.Quit();//清理word实例。
//需要字节来返回blob
byte[]pdfFileBytes=File.ReadAllBytes(tempPdfPath);
//删除临时文件
文件。删除(tempDocPath);
Delete(tempPdfPath);
//返回斑点
返回Convert.tobase64字符串(pdfFileBytes);
}
捕获(例外情况除外)
{
掷骰子;
}
}
客户:

        public async void btnConvert_Click(object sender, EventArgs e)
        {
            var response = await StartConvert();            

            foreach (SimpleResponse sr in response)
            {
                if (sr.Success)
                {
                    byte[] bte = Convert.FromBase64String(sr.Result.ToString());

                    string rs = RandomString(16, true);
                    string pdfFileName = tempPdfPath + rs + ".pdf";

                    if (File.Exists(pdfFileName))
                    {
                        File.Delete(pdfFileName);
                    }

                    System.IO.File.WriteAllBytes(pdfFileName, bte);
                }
                else
                {
                }
            }
        }

        private async Task<IEnumerable<SimpleResponse>> StartConvert()
        {
            var tasks = new List<Task<SimpleResponse>>();

            foreach (string s in docPaths)
            {
                byte[] bte = File.ReadAllBytes(s);

                tasks.Add(ConvertDocuments(Convert.ToBase64String(bte)));
            }

            return (await Task.WhenAll(tasks));
        }


        private async Task<SimpleResponse> ConvertDocuments(string requests)
        {
            using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
            {              
                client.BaseAddress = new Uri(BaseApiUrl);
                client.DefaultRequestHeaders.Add("Accept", "application/json");

                // Add an Accept header for JSON format.    
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//application/json
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);

                var data = JsonConvert.SerializeObject(requests);

                request.Content = new StringContent(data, Encoding.UTF8, "application/json");

                HttpResponseMessage response1 = await client.PostAsync(BaseApiUrl + ApiUrl, request.Content).ConfigureAwait(false);
                var response = JsonConvert.DeserializeObject<SimpleResponse>(await response1.Content.ReadAsStringAsync());

               
                return response;
            }            
        }

public async void btnConvert\u单击(对象发送方,事件参数e)
{
var response=wait StartConvert();
foreach(简单响应sr响应)
{
如果(高级成功)
{
字节[]bte=Convert.FromBase64String(sr.Result.ToString());
字符串rs=随机字符串(16,真);
字符串pdfFileName=tempPdfPath+rs+“.pdf”;
if(File.Exists(pdfFileName))
{
文件.Delete(pdfFileName);
}
System.IO.File.writealBytes(pdfFileName,bte);
}
其他的
{
}
}
}
专用异步任务StartConvert()
{
var tasks=新列表();
foreach(docpath中的字符串s)
{
字节[]bte=File.ReadAllBytes;
添加(ConvertDocuments(Convert.ToBase64String(bte));
}
返回(等待任务。当所有(任务));
}
专用异步任务转换文档(字符串请求)
{
使用(var-client=new-HttpClient(new-HttpClientHandler(){UseDefaultCredentials=true}))
{              
client.BaseAddress=新Uri(BaseApiUrl);
client.DefaultRequestHeaders.Add(“Accept”、“application/json”);
//为JSON格式添加Accept标头。
client.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);//应用程序/json
HttpRequestMessage请求=新的HttpRequestMessage(HttpMethod.Post,BaseApiUrl+ApiUrl);
var data=JsonConvert.SerializeObject(请求);
request.Content=newstringcontent(data,Encoding.UTF8,“application/json”);
HttpResponseMessageResponse1=await client.PostAsync(BaseApiUrl+ApiUrl,request.Content)。ConfigureAwait(false);
        public async void btnConvert_Click(object sender, EventArgs e)
        {
            var response = await StartConvert();            

            foreach (SimpleResponse sr in response)
            {
                if (sr.Success)
                {
                    byte[] bte = Convert.FromBase64String(sr.Result.ToString());

                    string rs = RandomString(16, true);
                    string pdfFileName = tempPdfPath + rs + ".pdf";

                    if (File.Exists(pdfFileName))
                    {
                        File.Delete(pdfFileName);
                    }

                    System.IO.File.WriteAllBytes(pdfFileName, bte);
                }
                else
                {
                }
            }
        }

        private async Task<IEnumerable<SimpleResponse>> StartConvert()
        {
            var tasks = new List<Task<SimpleResponse>>();

            foreach (string s in docPaths)
            {
                byte[] bte = File.ReadAllBytes(s);

                tasks.Add(ConvertDocuments(Convert.ToBase64String(bte)));
            }

            return (await Task.WhenAll(tasks));
        }


        private async Task<SimpleResponse> ConvertDocuments(string requests)
        {
            using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
            {              
                client.BaseAddress = new Uri(BaseApiUrl);
                client.DefaultRequestHeaders.Add("Accept", "application/json");

                // Add an Accept header for JSON format.    
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//application/json
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);

                var data = JsonConvert.SerializeObject(requests);

                request.Content = new StringContent(data, Encoding.UTF8, "application/json");

                HttpResponseMessage response1 = await client.PostAsync(BaseApiUrl + ApiUrl, request.Content).ConfigureAwait(false);
                var response = JsonConvert.DeserializeObject<SimpleResponse>(await response1.Content.ReadAsStringAsync());

               
                return response;
            }            
        }

        public string RandomString(int size, bool lowerCase = false)
        {
            var builder = new StringBuilder(size);

            // Unicode/ASCII Letters are divided into two blocks
            // (Letters 65–90 / 97–122):   
            // The first group containing the uppercase letters and
            // the second group containing the lowercase.  

            // char is a single Unicode character  
            char offset = lowerCase ? 'a' : 'A';
            const int lettersOffset = 26; // A...Z or a..z: length = 26  

            for (var i = 0; i < size; i++)
            {
                var @char = (char)_random.Next(offset, offset + lettersOffset);
                builder.Append(@char);
            }

            return lowerCase ? builder.ToString().ToLower() : builder.ToString();
        }

[HttpPost]
public async Task<SimpleResponse> Post([FromBody]string request)
{
    var response = new SimpleResponse();
    try
    {
        ...

        var result = await convert.CovertDocToPDF(...);

        ...
    }
    catch (Exception ex)
    {
        ...
    }
    
    return response;
}
var rs = Guid.NewGuid().ToString("N");
tempDocPath = tempDocPath + rs + ".docx";
tempPdfPath = tempPdfPath + rs + ".pdf";