在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);
 }

这里面临的问题是,如果我点击打印按钮不止一次,那么打印对齐是不正确的,我想如果我处理线程执行正确,那么它将是好的

在c#中处理线程用于打印

为了防止这个问题发生,我会在启动线程之前禁用打印按钮,然后在字符串被发送到打印机后重新启用它:

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]);
    }
}

但是要有一个"正确的"和(稍微高级的)解决方案,你应该考虑实现生产者/消费者设计模式。我建议使用数据流实现(如果它是新的开发)