【发布时间】:2021-09-23 13:50:39
【问题描述】:
为标签生成数据矩阵时,我的代码崩溃了。经过大量测试,我确定这是由于多线程造成的,但我无法确定原因。
我正在使用 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, int, byte[], int, int, int, int, int)
iTextSharp.text.pdf.BarcodeDatamatrix.GetEncodation(byte[], int, int, byte[], int, int, int, bool)
iTextSharp.text.pdf.BarcodeDatamatrix.Generate(byte[], int, 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, System.Threading.ContextCallback, object, 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);
}
我在应用程序中使用多线程来生成所有标签并立即开始打印它们,即使其他标签仍在生成。强迫他们等到其他人完成处理会显着降低应用程序的速度,因此删除多线程是最后的选择。
如何在不移除多线程的情况下防止此错误发生?
【问题讨论】:
-
在 Winforms 应用程序和控制台应用程序中尝试,无论是否使用线程,都无法重现错误。您确定要显示所有相关代码吗?
-
@evilmandarine 是的,我确定。我将此代码放在 WinForms 应用程序的按钮事件中。我可能会删除这个问题,因为我们使用了另一个似乎可以工作的库。另外,现在我们推出许可证时无需支付许可证费用。
-
@NicholaiRen - 代码不完整。要发生此错误,您必须在
ThreadPool.QueueUserWorkItemlambda 中使用i。您的问题是您没有捕获局部变量。不过,您必须发布完整的代码才能获得答案。 -
@NicholaiRen - 抱歉,我刚看到截图。显然您的代码是完整的,这意味着组件中必须有一些
static状态,以防止多个实例在不同的线程中运行。存在固有的竞争条件。 -
@Enigmativity 奇怪的是,我现在可以重现该问题。确实有静态字段:
private static int[][] f; private static int[][] switchMode;。使这些不是静态的并使类中的某些方法不是静态的可以解决问题:pastebin.com/PFnqBYQa。不确定我可以将其发布为答案。这个其他库也很旧,但效果很好:github.com/msmuelle-astrumit/DataMatrix.net.
标签: c# multithreading itext barcode datamatrix