微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用多线程使用 iTextSharp 生成数据矩阵导致崩溃

如何解决使用多线程使用 iTextSharp 生成数据矩阵导致崩溃

在为标签生成数据矩阵时,我的代码崩溃。经过大量测试,我确定是多线程造成的,但我无法确定原因。

我使用的是 iTextSharp v5.5.13.2(Nuget 包)。将复制错误代码如下:

        for(int i = 0; i < 10; i++)
        {
            ThreadPool.QueueUserWorkItem(x =>
            {
                iTextSharp.text.pdf.BarcodeDatamatrix dataMatrix = new iTextSharp.text.pdf.BarcodeDatamatrix();

                dataMatrix.Height = 18;
                dataMatrix.Width = 18;
                dataMatrix.ForceSquareSize = true;

                dataMatrix.Generate("TestData");
            });
            Console.WriteLine(i);
        }

这是错误

system.indexOutOfRangeException: 'Index was outside the bounds of the array.'
This exception was originally thrown at this call stack:
    iTextSharp.text.pdf.BarcodeDatamatrix.B256Encodation(byte[],int,byte[],int)
    iTextSharp.text.pdf.BarcodeDatamatrix.GetEncodation(byte[],bool)
    iTextSharp.text.pdf.BarcodeDatamatrix.Generate(byte[],int)
    iTextSharp.text.pdf.BarcodeDatamatrix.Generate(string)
    DataAccesstesting.Form1.Function1_Click.AnonymousMethod__59_0(object) in Form1.cs
    System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object)
    System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
    System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,bool)
    System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
    System.Threading.ThreadPoolWorkQueue.dispatch()
    ...
    [Call Stack Truncated]

如果我删除多线程,它运行得非常好。所以这段代码有效:

        for (int i = 0; i < 10; i++)
        {
            iTextSharp.text.pdf.BarcodeDatamatrix dataMatrix = new iTextSharp.text.pdf.BarcodeDatamatrix();

            dataMatrix.Height = 18;
            dataMatrix.Width = 18;
            dataMatrix.ForceSquareSize = true;

            dataMatrix.Generate("TestData");
            Console.WriteLine(i);
        }

       

我在应用程序中使用多线程来生成所有标签并立即开始打印它们,即使其他标签仍在生成。强制它们等待直到其他每个都完成处理会显着降低应用程序的速度,因此删除多线程是最后的选择。

如何在不删除多线程的情况下防止发生此错误

编辑: 我一直被告知我没有完整的代码。我再次测试,通过将我添加代码放入按钮事件中,我可以复制错误。这是一个屏幕截图。

Complete code for the error

解决方法

反编译库中的 BarcodeDatamatrix 确认 Generate 方法不是线程安全的,因为使用了以下字段(感谢 @Enigmativity 的有见地的评论):

private static int[][] f;
private static int[][] switchMode;

以下位置的类使这些字段(以及使用它们的其他方法)不是 static,从而解决了线程安全问题。重要提示:如果库/NuGet(实际上是此类)更新,如果您想使用最新版本,则可能需要再次执行此操作:
https://pastebin.com/PFnqBYQa

替代解决方案
使用可用的 DataMatrix.netherehere(旧库,不确定哪个更好)。

其他信息
我还测试了 ZXing.NET,但 FNC1 字符(例如组分隔符 \x1D)无法正常工作。这适用于上述库。

代码示例(用于替代库):

// ZXING: FNC1 not working
//var dm = new BarcodeWriter
//{
//    Format = BarcodeFormat.DATA_MATRIX,//    Options =
//    {
//        GS1Format = true,//        PureBarcode = true
//    }
//};

//var gs1Code = "0107612345678900171" + "\x1D" + "00503";
//var bmp = dm.Write(gs1Code);
//return bmp;


// Datamatrix.NET
var imageEncoder = new DmtxImageEncoder();
var options = new DmtxImageEncoderOptions
{
    ModuleSize = 8,MarginSize = 30,BackColor = Color.White,ForeColor = Color.Black,Scheme = DmtxScheme.DmtxSchemeAsciiGS1
};

var barcode = txt1.Text.Length == 13 
    ? "0" + txt1.Text
    : txt1.Text;

return imageEncoder.EncodeImage("01" + barcode
                              + "10" + txt2.Text + "\x1D"
                              + "21" + txt3.Text,options);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。