2015-09-26 40 views
0

我有一個WCF服務公開兩個端點(一個TCP和另一個REST)。我在WCF中有一個返回文件流的方法。 在我的客戶端應用程序中,我使用異步調用來開始下載文件並將其保存爲本地文件。完成線程後,我需要返回到主線程,以便我可以更新UI。爲此,我使用Dispatcher.Invoke。WCF文件在單獨線程上的流式下載掛起,同時返回到主線程

問題是,其餘端點似乎下載並保存文件,但TCP端點會引發超時錯誤。我的另一個問題是,在代碼完成並返回到Dispatcher.Invoke行的兩個端點中,它只是掛起而不能繼續。

我調試了它,服務調用正如預期的那樣在工作線程上工作,但當我嘗試使用Dispatcher.Invoke返回到主線程(UI)時,整個應用程序以某種方式掛起。我也嘗試過Dispatcher.BeginInvoke,但結果相同。

當我調用任何其他WCF方法(它返回JSON或數據約定)時,相同的應用程序和代碼工作正常。在這種情況下,我可以使用Dispatcher.Invoke回到主線程。但是有些時候,我正在調用WCF方法來下載它剛剛掛起的文件。

我試圖列出下面的代碼。不知道我在這裏做錯了什麼。我的webConfig設置爲最大尺寸。我不期待大文件(通常在2-5 MB之間)。

你能讓我知道我在做什麼錯嗎?我期望下載和寫入文件完成,然後移動到主線程。我希望它是流媒體,以便即使將來文件大小增加,我也可以處理。

任何指針/建議將有所幫助。

  • 吉里賈·
public static class Holder 
{ 
    public static Dispatcher CurrentDispatcher { get; set; } // Set when application loads 
} 

public class Downloader 
{ 


    public Downloader() 
    { 

    } 

    public void DownloadFileAndAct(string fileName) 
    { 
     AsyncCallback callback = new AsyncCallback(this.DownloadComplete); 
     Func<string, string> del = new Func<string, string>(this.DownloadStream); 
     del.BeginInvoke(fileName, callback, this); 
    } 

    private void DownloadComplete(IAsyncResult ar) 
    { 
     AsyncResult res = (AsyncResult)ar; 
     Func<string, string> objCaller = (Func<string, string>)res.AsyncDelegate; 
     var filePath = objCaller.EndInvoke(ar); 

     // The below code is where it just hangs 
     Holder.CurrentDispatcher.Invoke(new Action(() => 
     { 
      // Do some stuff on main thread like display the file in a selction list 
     })); 

    } 

    private string DownloadStream(string fileName) 
    { 
     TestServiceClient client = new TestServiceClient(); 

     //1st approach 
     var stream = client.DownloadFile(fileName); 
     client.Close(); 

     var savePath = @"D:\MySavedLocation\" + fileName; 

     using (var file = File.Create(savePath)) 
     { 
      stream.CopyTo(file); 
     } 

     // 2nd approach (tried this too) 
     //const int bufferSize = 2048; 
     //byte[] buffer = new byte[bufferSize]; 
     //using (FileStream outputStream = new FileStream(savePath, 
     // FileMode.Create, FileAccess.Write)) 
     //{ 
     // int bytesRead = client.DownloadFile(fileName).Read(buffer, 0, bufferSize); 
     // while (bytesRead > 0) 
     // { 
     //  outputStream.Write(buffer, 0, bytesRead); 
     //  bytesRead = client.DownloadFile(fileName).Read(buffer, 0, bufferSize); 
     // } 
     // outputStream.Close(); 
     //} 
     //client.Close(); 


     return savePath; 
    } 
} 

回答

0

我想你需要

//1st approach 
    var stream = client.DownloadFile(fileName); 
    //client.Close(); 

    var savePath = @"D:\MySavedLocation\" + fileName; 

    using (var file = File.Create(savePath)) 
    { 
     stream.CopyTo(file); 
    } 
    client.Close(); 

一個WCF流調用返回一個 '未讀' 流。在複製內容之前關閉客戶端。

我不知道爲什麼第二種方法(與緩衝區[])失敗,也許它有其他問題。

+0

Henk,如果我不清楚,我很抱歉,但這兩種方法都對我造成問題。我的代碼在調度程序行返回時掛起(在我的代碼示例中標記爲「//下面的代碼就是它掛起的位置」)。 - Giirja – Shankar

+0

對不起,關於初始代碼中的clinet.Close()。我的代碼正是你所說的。在CopyTo(..)後關閉客戶端。我的不好是一個錯字。 - Girija – Shankar

相關問題