我在我的应用程序中使用wkhtmltopdf
进行报告。然而,它按预期工作得很好。
问题 - 在下面的方法中,我将字符串源转换为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
方法与后台工作者进行沟通。
答案 0 :(得分:2)
使用Thread Class,它将在主线程以外的后台线程中运行您的方法。 更多的是你在你的方法中返回null,所以最好使返回类型为void并且不返回null。
Thread threadObj = new Thread(new ThreadStart(()=>ConverToPdf("a","b")));
threadObj.Start();
更新:我假设您使用的是Windows窗体。根据您的更新,您可以轻松地看到主要方法需要响应才能进一步执行。现在为此我建议你在后台线程中显示一些进度条,以便我不会停止应用程序。当converttoPDF
方法完成时,进程停止进度条。在这种情况下,您的应用程序不会卡住,您将根据需要获得响应。
答案 1 :(得分:0)
private void Button1_Click(object sender, EventArgs e)
{
bgworker.RunWorkerAsync();
}
private void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
ConverToPdf(source, commandLocation);
}