我有一个方法可以并行加载并运行报表布局。所有报告将使用相同的games
。由于线程每次尝试访问同一资源时都会因异常而失败,因此我使用了baselayout.xml
来锁定文件。
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));
}
Conver将运行以下代码:
private void RunReportsParallel(List<ReportObject> coverterList)
{
try
{
Parallel.ForEach(coverterList, (currentObject) => {
currentObject.Convert();
});
}
catch (Exception e)
{
smlLogger.Error(Helper.SetLogLine(e.Message, processId));
throw;
}
}
在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;
}
中引发错误的行:
ReportAkontorechnung.cs
最后,错误:
this.LoadLayout(Helper.LoadReport("ReportAkontoZusammenfassung"));
消息:
内部异常1:NullReferenceException:Der Objektverweis wurde 可以在Obestktinstanz电影节上观看。民主运动 奥布涅克斯坦斯坦节日音乐节。 (对象引用未指向对象实例。)
如何解决返回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)
的问题?
编辑:
利亚姆的言论似乎可以解决大多数问题。不使用并行加载,而是并行运行。我本来想知道看到这种选择的错误。
答案 0 :(得分:5)
您正在获取本地对象的锁! 将_locker声明为类中的私有静态对象(如果需要在实例中使用锁,请不要使用static。但是,如果需要对此类的所有实例使用锁,请使用static。)
private static readonly object _locker = new object(); //readonly to avoid reassignment. static to lock on all instances.
然后以{p> 1的身份锁定
_locker
尽管可以有一些方法来进行无锁并行报告。
答案 1 :(得分:0)
使用PLINQ会非常简单。从名称开始,依次将它们映射到资源,然后并行将资源映射到其处理后的输出。
可能看起来像这样:
const string[] reportNames = { "ReportA", "ReportB" };
var results = reportNames
.AsSequential()
.Select
(
name => Resources.ResourceManager.GetObject(name)
)
.AsParallel()
.Select
(
reportData => DoSomethingCpuBound
(
new XmlTextReader(new MemoryStream((byte[])reportData))
)
)
.ToList();
这样,资源将按顺序加载,但处理是并行进行的。另外,此解决方案完全避开了任何线程问题,因此不需要任何锁定。
注意:确实不需要AsSequential()
调用(默认是顺序调用),但出于说明目的,我将其放在此处。