如何避免用lock语句返回null?

Pet*_*ter 0 c# activereports multithreading xmlreader parallel.foreach

我有一种方法可以并行加载并运行报表布局。所有报告将使用相同的baselayout.xml。由于线程每次尝试访问同一资源时都会因异常而失败,因此我使用了a lock来锁定文件。

public static XmlTextReader LoadReport(string reportName)
{
    object _locker = new object();
    object reportData;
    lock (_locker)
    {
        reportData = Resources.ResourceManager.GetObject(reportName);
    }
    return new XmlTextReader(new MemoryStream((byte[])reportData));
}
Run Code Online (Sandbox Code Playgroud)

并行方法如下所示:

private void RunReportsParallel(List<ReportObject> coverterList)
{
    try
    {
        Parallel.ForEach(coverterList, (currentObject) => {
            currentObject.Convert();
        });    
    }
    catch (Exception e)
    {
        smlLogger.Error(Helper.SetLogLine(e.Message, processId));
        throw;
    }
}
Run Code Online (Sandbox Code Playgroud)

Conver将运行以下代码:

public override SectionReport GetMainReport()
{
    SectionReport mainReport = new SectionReport();
    XMLDataSource datasource = new XMLDataSource(null, "//AkontoRechnung");
    datasource.LoadXML(rechnungsdaten.ToString());
    mainReport = new ReportAkontorechnung(datasource, reportConfiguration, Language, NoPrintOut);
    try
    {
        mainReport.Run();
    }
    catch (Exception e)
    {
        smlLogger.Error(Helper.SetLogLine(string.Format("Error creating Report: {0}", e.Message), processId));
        throw;
    }
    return mainReport;
}
Run Code Online (Sandbox Code Playgroud)

引发错误的行ReportAkontorechnung.cs

this.LoadLayout(Helper.LoadReport("ReportAkontoZusammenfassung")); 最后,错误:

bei GrapeCity.ActiveReports.Controls.Image.Load(Stream stream, Boolean checkMagic)
bei GrapeCity.ActiveReports.SectionReport.#Pyb(XmlNode node)
bei GrapeCity.ActiveReports.SectionReport.#Qyb(XmlDocument layoutDoc, Boolean checkNames)
bei GrapeCity.ActiveReports.SectionReport.LoadLayout(XmlReader reader, ArrayList& errors)
bei GrapeCity.ActiveReports.SectionReport.LoadLayout(XmlReader reader)   
bei GFPrinting.Domain.ReportAkontorechnung.InitializeReport() 
     in C:\Dev\GFPrinting\Ruf.GFPrinting\branch\Concurrent\trunc\Source\SMLPrinting\Domain\ReportAkontorechnung.cs:Zeile 108.
bei GFPrinting.Domain.ReportAkontorechnung..ctor(XMLDataSource reportNavigation, ReportConfiguration reportConfiguration, String reportLanguage, Boolean noPrintout) 
     in C:\Dev\GFPrinting\Ruf.GFPrinting\branch\Concurrent\trunc\Source\SMLPrinting\Domain\ReportAkontorechnung.cs:Zeile 79.
bei GFPrinting.Domain.Akontorechnung.GetMainReport() 
    in C:\Dev\GFPrinting\Ruf.GFPrinting\branch\Concurrent\trunc\Source\SMLPrinting\Domain\Change\Akontorechnung.cs:Zeile 42.
bei GFPrinting.Domain.Change.ReportObject.Convert() 
    in C:\Dev\GFPrinting\Ruf.GFPrinting\branch\Concurrent\trunc\Source\SMLPrinting\Domain\Change\ReportObject.cs:Zeile 33.
bei GFPrinting.Domain.Rechnungshandler.<>c.<RunReportsParallel>b__13_0(ReportObject currentObject) 
    in C:\Dev\GFPrinting\Ruf.GFPrinting\branch\Concurrent\trunc\Source\SMLPrinting\Domain\Change\Rechnungshandler.cs:Zeile 103.
bei System.Threading.Tasks.Parallel.<>c__DisplayClass31_0`2.<ForEachWorker>b__0(Int32 i)
bei System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
bei System.Threading.Tasks.Task.InnerInvoke()
bei System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
bei System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object)
Run Code Online (Sandbox Code Playgroud)

信息:

内部异常1:NullReferenceException:Objektinstanz festgelegt发生的异常。Objektverweis纪念日,Objektinstanz纪念日。(对象引用未指向对象实例。)

我该如何解决退货问题null

编辑
利亚姆的评论似乎可以解决大多数问题。不使用并行加载,而是并行运行。我被固定在错误,以看到这样的选择。

Sar*_*hra 5

您正在获取对本地对象的锁定!将_locker声明为类中的私有静态对象(如果需要在实例中使用锁,请不要使用static。但是,如果需要对此类的所有实例使用锁,请使用static。)

private static readonly object _locker = new object(); //readonly to avoid reassignment. static to lock on all instances.
Run Code Online (Sandbox Code Playgroud)

然后锁定_locker

lock(_locker)
{

}
Run Code Online (Sandbox Code Playgroud)

尽管可能有一些方法可以进行无锁并行报告。

  • OP应该使用“私有静态只读对象_lock = new Object()”来防止重新分配。 (2认同)