2014-07-22 38 views
8

Uygulamamda bir kilitlenme oluşturduğum konusunda oldukça olumluyım ve sorunu nasıl çözeceğimi bilmiyorum. Birkaç hareketli parçam var ve async ve await'a yeni sahibim.Async Deadlock?

ben şöyle bir dosyayı yükleyen bir müşterim var:

public static async Task<string> UploadToService(HttpPostedFile file, string authCode, int id) 
{ 
    var memoryStream = new MemoryStream(); 
    file.InputStream.CopyTo(memoryStream); 

    var requestContent = new MultipartFormDataContent(); 
    var fileContent = new ByteArrayContent(memoryStream.ToArray()); 
    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType); 
    requestContent.Add(fileContent, "file", file.FileName); 

    using (var httpClient = new HttpClient()) 
    { 
     httpClient.BaseAddress = new Uri(BaseUrl); 
     httpClient.DefaultRequestHeaders.Accept.Clear(); 

     var message = 
      await 
       httpClient.PostAsync(
        string.Format("Upload?authCode={0}&id={1}", authCode, id), 
        requestContent); 

     return await message.Content.ReadAsStringAsync(); 
    } 
} 

dosyayı aldıktan parça: O ile başladı tüm edilmektedir

[HttpPost] 
public Task<HttpResponseMessage> Upload(string authCode, int id) 
{ 
    var request = Request; 

    var provider = new CustomMultipartFormDataStreamProvider(root); 

    var task = 
     request.Content.ReadAsMultipartAsync(provider) 
      .ContinueWith(o => 
      { 
       // ... 
       // Save file 
       // ... 

       return new HttpResponseMessage() 
       { 
        Content = new StringContent("File uploaded successfully"), 
        StatusCode = HttpStatusCode.OK 
       }; 
      }); 

    return task; 
} 

aşağıdadır:

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (IsPostBack) 
    { 
     var file = HttpContext.Current.Request.Files[0]; 

     var response = UploadToService(file, hiddenAuthCode.Value, int.Parse(hiddenId.Value)); 
    } 
} 

Her şey çalışıyor görünüyor, ancak PostAsync asla task iade edildi. await ... PostAsync ... görevinin durumunu WaitingForActivation olduğunu görebiliyorum ama bunun ne anlama geldiğini tam olarak bilmiyorum (unutmayın, bu şeyler için bir n00b değilim). Dosyam doğru konuma kaydedildi, ancak uygulama hizmetimin yanıtını asla kabul etmiyor.

Eğer birisi bana doğru yönde işaret ederse çok memnun olur.

cevap

6

Sorun şu ki, UploadToService'u Page_Load içinde yangın ve unut-boz şeklinde çağırmanızdır. İstek işleme bu görev tamamlanmadan bitiyor.

Bu WebForms sayfasından <%@ Page Async="true" ...> kullanmanız ve <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> numaranızı web.config numaranıza yazmanız gerekir.

Sonra RegisterAsyncTask kullanmak, kod şu şekilde görünecektir: Böyle

file.InputStream.CopyTo(memoryStream); 

:

await file.InputStream.CopyToAsync(memoryStream); 

Yan not
protected void Page_Load(object sender, EventArgs e) 
{ 
    if (IsPostBack) 
    { 
     var file = HttpContext.Current.Request.Files[0]; 

     RegisterAsyncTask(new PageAsyncTask(() => UploadToService(file, 
      hiddenAuthCode.Value, int.Parse(hiddenId.Value)))); 
    } 
} 

, bu bölümü artırabilirsiniz ve 'u async/await ile değiştirin:

[HttpPost] 
public async Task<HttpResponseMessage> Upload(string authCode, int id) 
{ 
    var request = Request; 

    var provider = new CustomMultipartFormDataStreamProvider(root); 

    await request.Content.ReadAsMultipartAsync(provider); 

    return new HttpResponseMessage() 
    { 
     Content = new StringContent("File uploaded successfully"), 
     StatusCode = HttpStatusCode.OK 
    }; 
} 

Related: "Using Asynchronous Methods in ASP.NET 4.5".

+0

Bunu "RegisterAsyncTask" olarak değiştirdikten sonra, "System.Web.UI.PageAsyncTask" türünde bir parametre atanabilir. Dönüş türümü değiştirmeyi denedim, ancak bu diğer bazı hatalara neden oldu. Herhangi bir fikir? – Joe

+0

@Joe, bir daha tweak: 'new PageAsyncTask (() => UploadToService (dosya, ...))', argüman 'Func 'dur. – Noseratio

+1

Teşekkür ederiz! Değişiklikleri yaptıktan sonra, daha fazla kilitlenme yok. – Joe