2014-08-30 189 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); 
     }