1 The right procedure
Public classAvatercontroller:baseapicontroller{[httppost] Public AsyncTask<ihttpactionresult> Uploadavater (intuserId) {AVATARBLL PICTUREBLL=NewAVATARBLL ( This. Request); awaitPicturebll.uploadavatar (userId); returnOk (); }//Other Action} Public classavatarbll{Privatehttprequestmessage httprequestmessage; PublicAVATARBLL (Httprequestmessage httprequestmessage) { This. Httprequestmessage =httprequestmessage;} Public AsyncTask Uploadavatar (intuserId) { if(! HttpRequestMessage.Content.IsMimeMultipartContent ("Form-data")) { //Throw Exception }//get the data that the client passes to the serverlist<byte> list =Newlist<byte>(); awaitHttpRequestMessage.Content.ReadAsMultipartAsync (). ContinueWith (multipartcontent = { if(multipartcontent.isfaulted | |multipartcontent.iscanceled) {//Throw Exception } foreach(varContentinchmultipartContent.Result.Contents) {varb =content. Readasbytearrayasync (). Result; List. AddRange (b); } });//other parts (storing data in MongoDB and other business logic)}}
2 Wrong procedure
Public classAvatercontroller:baseapicontroller{[httppost] PublicIhttpactionresult Uploadavater (intuserId) {AVATARBLL PICTUREBLL=NewAVATARBLL ( This. Request); Picturebll.uploadavatar (USERID); returnOk (); }//Other Action} Public classavatarbll{Privatehttprequestmessage httprequestmessage; PublicAVATARBLL (Httprequestmessage httprequestmessage) { This. Httprequestmessage =httprequestmessage;} Public voidUploadavatar (intuserId) { if(! HttpRequestMessage.Content.IsMimeMultipartContent ("Form-data")) { //Throw Exception }//get the data that the client passes to the serverlist<byte> list =Newlist<byte>(); MemoryStream Ms=NewMemoryStream (); Try{Multipartmemorystreamprovider Mmsp=NewMultipartmemorystreamprovider (); varTask = httprequestmessage.content.readasmultipartasync<multipartmemorystreamprovider> (Mmsp,100000); Task. Wait (); varContents =task. result.contents; foreach(varCinchcontents) { varb =C.readasbytearrayasync (); B.wait (); List. AddRange (B.result); } } Catch(AggregateException ex) {}//other parts (storing data in MongoDB and other business logic)}}
3 Error Phenomena:
In the second way, if the amount of data that the client uploads to the service (calling Uploadavater uploaded Data ) is less than the size of the buffer set by the server, then the file can be uploaded normally, if it is larger than the size of the buffer set by the server, it will not be uploaded properly. Debug the server-side code when executing to a task. Wait (); when this line of statements occurs, the client waits until the client call times out and never returns the call result, and a deadlock has occurred!!! Use httprequestmessage.content.readasmultipartasync<multipartmemorystreamprovider> (MMSP, 1000); set the buffer size to 1000bit. This method has several overloaded methods, one of which is to not display the set buffer size, then the buffer size is the default.
4 Error point analysis for the second method:
See WEB API DLL settings in the source code:
can see the default The buffer area size is 32*1024, that is, 32K, then upload more than 32k without setting the buffer size, why a deadlock occurs, and the buffer setting exceeds the size of the upload file why does the deadlock occur? The possibility of a deadlock occurs regardless of whether the buffer size is set sufficiently large.
The main method is shown in the method body with the following code:
The core approach to this code:
The above method iterates through the request data, and when the buffer size is set less than the amount of data that the client sends to the server, it is necessary to iterate through the data several times, and each time the data is read, it calls two async methods:
However, The return value of the Readasmultipartasync method is task<t>(T is streamprovider), so when calling the Task.wait () method Waits,the Readasmultipartasync method also waits for asynchronous processing Streamprovider to return results, which creates a deadlock.
5 First Method Why is there no deadlock?
The first method uses awaitto implement the synchronization mechanism without invoking the task.wait () method, thus avoiding a,B The possibility that two blocks of code will wait for the result to return and cause a deadlock.
ASP. NET Web API File upload