C#打印和穿线
我需要用户能够扫描一系列项目,并为每个项目打印x个标签。我目前正试图使用后台工作人员来完成这项工作,但我遇到了一个问题,他们扫描项目的速度太快,后台工作人员阻塞的每个项目都有太多的标签要打印。这就是我为每次扫描生成后台工作线程的方式,因为在打印大量标签时发生了争用C#打印和穿线,c#,multithreading,printing,C#,Multithreading,Printing,我需要用户能够扫描一系列项目,并为每个项目打印x个标签。我目前正试图使用后台工作人员来完成这项工作,但我遇到了一个问题,他们扫描项目的速度太快,后台工作人员阻塞的每个项目都有太多的标签要打印。这就是我为每次扫描生成后台工作线程的方式,因为在打印大量标签时发生了争用 private void RunPrintWorker() { if (printWorker.IsBusy) { printWorker = new Backgrou
private void RunPrintWorker()
{
if (printWorker.IsBusy)
{
printWorker = new BackgroundWorker();
printWorker.DoWork += new DoWorkEventHandler(printWorker_DoWork);
printWorker.RunWorkerAsync();
}
else
printWorker.RunWorkerAsync();
}
我没有从后台工作人员那里得到任何异常,它只是似乎没有足够快地创建线程。我使用多线程比较新,所以有人能告诉我我做错了什么吗
谢谢
编辑:谢谢大家的建议和阅读材料,这真的很有帮助。标签的打印顺序并不重要,因为它们扫描速度非常快,而且标签也只打印到一台打印机上。我将在实现启动并运行后标记一个答案
编辑:奥斯汀,下面是我如何设置打印方法的。在我调用RunPrintWorker方法中的LabelPrinter.PrintLabels之前。现在我正在重做这个,我不知道要传递什么到SizeQueue方法中。我应该将新创建的打印文档传递给它吗
public class LabelPrinter
{
private int CurrentCount = 0;
private List<int> _selectedRows = new List<int>();
public List<int> SelectedRows
{
get { return _selectedRows; }
set { _selectedRows = value; }
}
private string _selectedTemplate;
public string SelectedTemplate
{
get { return _selectedTemplate; }
set { _selectedTemplate = value; }
}
private string _templateDirectory = string.Empty;
public string TemplateDirectory
{
get { return _templateDirectory; }
set { _templateDirectory = value; }
}
public void PrintLabels(PrintDocument printDoc, PageSettings pgSettings, PrinterSettings printerSettings, List<int> selectedRows, string selectedTemplate, string templateDir)
{
this._selectedRows = selectedRows;
this._selectedTemplate = selectedTemplate;
this._templateDirectory = templateDir;
printDoc.DefaultPageSettings = pgSettings;
printDoc.PrinterSettings = printerSettings;
printDoc.PrinterSettings.MaximumPage = selectedRows.Count();
printDoc.DefaultPageSettings.PrinterSettings.ToPage = selectedRows.Count();
printDoc.PrinterSettings.FromPage = 1;
printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage);
printDoc.Print();
}
private void printDoc_PrintPage(object sender, PrintPageEventArgs e)
{
CurrentCount = DrawLabel.DrawLabelsForPrinting(e, SelectedTemplate, SelectedRows, CurrentCount, TemplateDirectory);
}
}
公共类标签打印机
{
私有int CurrentCount=0;
私有列表_selectedRows=新列表();
公共列表选定的行
{
获取{return\u selectedRows;}
设置{u selectedRows=value;}
}
私有字符串_selectedTemplate;
公共字符串SelectedTemplate
{
获取{return\u selectedTemplate;}
设置{u selectedTemplate=value;}
}
私有字符串_templateDirectory=string.Empty;
公共字符串模板目录
{
获取{return\u templateddirectory;}
设置{u templateDirectory=value;}
}
公共无效打印标签(打印文档打印文档、页面设置、页面设置、打印设置、打印设置、列表选择的箭头、字符串选择的模板、字符串模板目录)
{
这。\ u selectedRows=selectedRows;
这.\u selectedTemplate=selectedTemplate;
这是._templateDirectory=templateDir;
printDoc.DefaultPageSettings=pgSettings;
printDoc.PrinterSettings=PrinterSettings;
printDoc.PrinterSettings.MaximumPage=selectedRows.Count();
printDoc.DefaultPageSettings.PrinterSettings.ToPage=selectedRows.Count();
printDoc.PrinterSettings.FromPage=1;
printDoc.PrintPage+=新的PrintPageEventHandler(printDoc\u PrintPage);
printDoc.Print();
}
私有void printDoc_PrintPage(对象发送方,PrintPageEventArgs e)
{
CurrentCount=DrawLabel.DrawLabels用于打印(e,SelectedTemplate,SelectedRows,CurrentCount,TemplateDirectory);
}
}
尝试将项目添加到队列中(例如,队列
),并让BackgroundWorker处理该队列
编辑:添加一些简单、未经测试、可能适合您的代码。我会用它的处理器封装打印队列,然后只发送作业给它
class SimpleLabelPrinter
{
public bool KeepProcessing { get; set; }
public IPrinter Printer { get; set; }
public SimpleLabelPrinter(IPrinter printer)
{
Printer = printer;
}
/* For thread-safety use the SizeQueue from Marc Gravell (SO #5030228) */
SizeQueue<string> printQueue = new SizeQueue<string>();
public void AddPrintItem(string item)
{
printQueue.Enqueue(item);
}
public void ProcessQueue()
{
KeepProcessing = true;
while (KeepProcessing)
{
while (printQueue.Count > 0)
{
Printer.Print(printQueue.Dequeue());
}
Thread.CurrentThread.Join(2 * 1000); //2 secs
}
}
}
class Program
{
static void Main(string[] args)
{
SimpleLabelPrinter printer1 = new SimpleLabelPrinter(...);
SimpleLabelPrinter printer2 = new SimpleLabelPrinter(...);
Thread printer1Thread = new Thread(printer1.ProcessQueue);
Thread printer2Thread = new Thread(printer2.ProcessQueue);
//...
printer1.KeepProcessing = false; //let the thread run its course...
printer2.KeepProcessing = false; //let the thread run its course...
}
}
您需要实现一个排队系统。看看Queue类,并在其中对打印文档进行排队。启动一个后台线程(在这种情况下不是backgroundworker),让它定期检查队列中的更多项目,如果可以的话,打印它们 在backgroundworker中运行如下方法:
private void PrintLoop()
{
while (true)
{
if (documents.Count > 0)
{
PrintDocument document = documents.Dequeue();
document.Print();
}
else
{
Thread.Sleep(1000);
}
}
}
为每台打印机创建一个BackgroundWorker,并将每个打印到不同的打印机。基本上,您要做的是,如果打印机忙,请使用另一个worker覆盖您的printWorker对象,然后启动该对象。然后,就没有对旧辅助对象的引用,也不进行任何清理 这里面有各种各样的问题
- 后台工作人员必须在完成后进行处理,以防止泄漏
- 创建更多的后台工作并不意味着打印机将运行得更快,它只是意味着有更多的工人试图同时到达打印机
private void PrintLoop()
{
while (true)
{
if (documents.Count > 0)
{
PrintDocument document = documents.Dequeue();
document.Print();
}
else
{
Thread.Sleep(1000);
}
}
}
ThreadPool.QueueUserWorkItem(new WaitCallback(o=>{printWorker_DoWork();}));