在c#中处理线程用于打印
本文关键字:用于 打印 线程 处理 | 更新日期: 2023-09-27 18:14:29
我想做打印从我的。net项目作为后台工作作为一个线程,为此,我所做的是,首先收集每个输出字符串到字符串的集合,像这样:
myOutputStringCollection.Add(str);
然后在收集了所有我想要发送给打印机的行之后,我写了这样的代码来执行一个线程:
public static void printAllLines()
{
Thread t = new Thread(sendToPrinter);
t.Start(); //starts the thread
}
和发送到打印机的功能如下:
public static void sendToPrinter()
{
int count = myOutputStringCollection.Count;
string[] myArray = new string[count];
myOutputStringCollection.CopyTo(myArray, 0);
for (int i = 0; i < count; i++)
{
SendStringToPrinter(myArray[i].ToString());
}
Array.Clear(myArray, 0, myArray.Length);
}
这里面临的问题是,如果我点击打印按钮不止一次,那么打印对齐是不正确的,我想如果我处理线程执行正确,那么它将是好的
为了防止这个问题发生,我会在启动线程之前禁用打印按钮,然后在字符串被发送到打印机后重新启用它:
public static void printAllLines()
{
btnPrint.Enabled = false;
Thread t = new Thread(sendToPrinter);
t.Start();//starts the thread
}
public static void sendToPrinter()
{
int count = myOutputStringCollection.Count;
string[] myArray = new string[count];
myOutputStringCollection.CopyTo(myArray, 0);
for (int i = 0; i < count; i++)
{
SendStringToPrinter(myArray[i]); // no need for ToString() as it's already a string
}
// re-enable print button by marshalling to UI thread
this.Invoke(new MethodInvoker(delegate()
{
btnPrint.Enabled = true;
}));
}
不需要调用Array.Clear(),因为myArray是一个局部变量,因此无论如何都会在sendtopprinter方法(和线程)结束时被销毁。
根据Sandy的回答,禁用按钮是一件事。最重要的是,你应该在sendstringtopprinter周围加一个锁,这样一次只有一个线程在访问它。简单的例子:
lock (lockObj)
{
SendStringToPrinter(myArray[i].ToString());
}
lockObj应该是一个不可变对象。下面的代码对你有用:
private static readonly object lockObj = new object();
阅读更多关于http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.71).aspx
我认为你必须等待所有正在运行的线程完成它们的工作,然后清除数组,即使你不需要完全清除数组。
另一点,你的数组可能会很长,创建这么多线程肯定是低效的。
你可以在后一种情况下考虑线程池
作为您的问题的直接解决方案,您需要同步访问您的共享资源(myOutputStringCollection
字段):
将字符串添加到集合的位置:
lock(myOutputStringCollection)
{
myOutputStringCollection.Add(str);
}
那么sendToPrinter
方法应该是这样的:
public static void sendToPrinter()
{
string[] myArray;
lock(myOutputStringCollection)
{
myArray = myOutputStringCollection.ToArray();
myOutputStringCollection.Clear();
}
for (int i = 0; i < myArray.Length; i++)
{
SendStringToPrinter(myArray[i]);
}
}
但是要有一个"正确的"和(稍微高级的)解决方案,你应该考虑实现生产者/消费者设计模式。我建议使用数据流实现(如果它是新的开发)