2014-08-30 187 views
0

我在應用程序中使用wkhtmltopdf進行報告。不過,它的效果很好如何在後臺運行進程? c#

問題- 在下面的方法爲我將字符串源轉換爲pdf和寫入字節。

注 - 我正在讀取所有字節並嘗試運行進程之前正在啓動進程。 主要問題是運行此過程的背景能力。我不知道這個過程在後臺運行。

目前發生的事情是,直到沒有生成PDF,整個應用程序進入暫停模式。這是後臺進程無法正常工作。

如何修改此過程,使其在後臺工作而無需停止我的應用程序?

我已閱讀關於任務工廠和多個線程,但我沒有得到線索。

爲PDF

方法轉換 -


public byte[] ConverToPdf(string source, string commandLocation) 
     { 

      string HtmlToPdfExePath = Server.MapPath("~/wkhtmltopdf.exe"); 
      Process p; 
      ProcessStartInfo psi = new ProcessStartInfo(); 
      psi.FileName = Path.Combine(commandLocation, HtmlToPdfExePath); 
      psi.WorkingDirectory = Path.GetDirectoryName(psi.FileName); 
      psi.UseShellExecute = false; 
      psi.CreateNoWindow = true; 
      psi.RedirectStandardInput = true; 
      psi.RedirectStandardOutput = true; 
      psi.RedirectStandardError = true; 
      string args = "-q -n "; 
      args += "--enable-javascript "; 
      args += "--enable-plugins "; 
      args += "--disable-smart-shrinking "; 
      args += "--margin-bottom 20 "; 
      args += "--margin-left 20 "; 
      args += "--margin-right 20 "; 
      args += "--margin-top 20 "; 
      args += "--orientation Landscape "; 
      args += "--outline-depth 0 "; 
      args += "--page-size A4 "; 
      args += "--encoding utf-8"; 
      args += " - -"; 
      psi.Arguments = args; 
      p = Process.Start(psi); 

      try 
      { 
       using (StreamWriter stdin = new StreamWriter(p.StandardInput.BaseStream, Encoding.UTF8)) 
       { 
        stdin.AutoFlush = true; 
        stdin.Write(source); 
       } 

       byte[] buffer = new byte[32768]; 
       byte[] file; 
       using (var ms = new MemoryStream()) 
       { 

        while (true) 
        { 
         int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length); 
         if (read <= 0) 
          break; 
         ms.Write(buffer, 0, read); 
        } 
        file = ms.ToArray(); 
       } 
       p.StandardOutput.Close(); 
       p.WaitForExit(60000); 
       int returnCode = p.ExitCode; 
       p.Close(); 
       if (returnCode == 0) 
        return file; 
       else 
        return file; 
      } 
      catch (Exception ex) 
      { 
       ModelState.AddModelError("Could not create PDF", ex); 
      } 
      finally 
      { 
       p.Close(); 
       p.Dispose(); 
      } 

      return null; 
     } 

更新 - 我其實是試圖找到後臺工作的方式做自己的工作,並從上述方法返回字節。

我與後臺工作者調用此方法的主要目的是與調用結果的位置進行通信。

public ActionResult DuesPDF() 
     { 
      var relativePath = "~/Views/Shared/_TestView.cshtml"; 
      string content; 
      var view = ViewEngines.Engines.FindView(ControllerContext, relativePath, null); 
      using (var writer = new StringWriter()) 
      { 
       TempData["req"] = "DuesAndOverDuesChart"; 
       var context = new ViewContext(ControllerContext, view.View, ViewData, TempData, writer); 
       view.View.Render(context, writer); 
       writer.Flush(); 
       content = writer.ToString(); 
       byte[] pdfBuf = ConverToPdf(content, Server.MapPath("~/PDF/")); 

       if (pdfBuf == null) 
        return null; 
       return File(pdfBuf, "application/pdf"); 
      } 
     } 

下面是這個方法我打電話PDF方法 - ConverToPdf(content, Server.MapPath("~/PDF/"))

注意 -

我與後臺工作,要求通信從上面ConverToPdf方法。

回答

2

使用線程類它會在除主線程以外的後臺線程中運行您的方法。 在你的方法中,你將返回null,所以最好使返回類型爲void並且不返回null。

Thread threadObj = new Thread(new ThreadStart(()=>ConverToPdf("a","b"))); 
threadObj.Start(); 

更新:我假設你正在使用Windows窗體。根據你的更新,你可以很容易地看到你的主要方法需要進一步執行響應。現在爲此,我建議你在後臺線程中顯示一些進度條,這樣我就不會停止應用程序。並且當converttoPDF方法結束時,處理停止進度條。在這種情況下,您的應用程序不會卡住,您將獲得所需的響應。

+0

使它返回類型void,不會幫助我。因爲在那裏它需要回傳給它被調用的方法。 – user3163213 2014-08-30 07:53:51

+0

但您爲什麼要再次與該方法進行通信?讓它變得簡單,它認爲你的邏輯有點混亂。如果您希望響應執行得更遠,則不要在後臺線程中運行該方法,或者如果要在後臺線程中運行,則意味着您的主線程不需要響應就可以進一步執行。我希望你明白我的觀點。 – 2014-08-30 08:01:13

+0

我誤以爲我的問題。讓我更新它以獲得更多理解 – user3163213 2014-08-30 08:04:01

0
private void Button1_Click(object sender, EventArgs e) 
     { 
      bgworker.RunWorkerAsync(); 
     } 
private void bgworker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      ConverToPdf(source, commandLocation); 
     }