2

I asked this question on the ESRI forums but got nothing so I thought I would try it here (hope that is consider ok). I am creating an extension for ArcMap 10.2 using Visual Studio 2012 C# WPF. Consider this code snippet:

//Open the CSV file
IWorkspaceFactory WorkspaceFactory = new TextFileWorkspaceFactoryClass();
IFeatureWorkspace FeatureWorkspace = (IFeatureWorkspace)WorkspaceFactory.OpenFromFile(FilePath, 0);
ITable Table = FeatureWorkspace.OpenTable(FileName);

IStandaloneTable StandaloneTable = new StandaloneTableClass();
StandaloneTable.Table = Table;

IMap Map = MxDocument.FocusMap;
IStandaloneTableCollection StandaloneTableCollection = (IStandaloneTableCollection)Map;
StandaloneTableCollection.AddStandaloneTable(StandaloneTable);

//Create the Event Layer of the data source
IDataset Dataset = (IDataset)StandaloneTable;
IName TableName = Dataset.FullName;

IXYEvent2FieldsProperties XYEvent2FieldsProperties = new XYEvent2FieldsPropertiesClass();
XYEvent2FieldsProperties.XFieldName = ColumnX;
XYEvent2FieldsProperties.YFieldName = ColumnY;
XYEvent2FieldsProperties.ZFieldName = String.Empty;

IXYEventSourceName XYEventSourceName = new XYEventSourceNameClass();
XYEventSourceName.EventProperties = XYEvent2FieldsProperties;
XYEventSourceName.EventTableName = TableName;
XYEventSourceName.SpatialReference = SpatialReference;

IName XYEventName = (IName)XYEventSourceName;
IXYEventSource XYEventSource = (IXYEventSource)XYEventName.Open();

//Map the Event Layer
IFeatureLayer FeatureLayer = new FeatureLayerClass();
FeatureLayer.FeatureClass = (IFeatureClass)XYEventSource;
FeatureLayer.Name = FileName;

//Add the layer extension
ILayerExtensions LayerExtensions = (ILayerExtensions)FeatureLayer;
LayerExtensions.AddExtension(new XYDataSourcePageExtensionClass());

//Add it to the MXD
Map.AddLayer(FeatureLayer);
FeatureLayer.Selectable = true;
MxDocument.UpdateContents();
MxDocument.ActiveView.Refresh();

This is from a function in a class that is called from the UI Form. What I am doing is creating a CSV file from a .Net DataTable (not in the above code), adding the CSV as a Table in Sources of the TOC, and then mapping the Table as Layer (the last 4 lines above).

This all works fine if I do it on the main UI thread of the Form when the user clicks a button. But what I would like to do is it put it on a TPL thread since it can be a time consuming process and here is when I run into problems. The above code will CRASH arcmap completely. It cannot even be trapped.

I noticed two things. One, the crash happens on the line "Map.AddLayer(FeatureLayer);" so when it tries to add to the layer collection. So I removed that line just to see what the Table in sources looks like. Second, looking at that Table I notice that if I right click it the options to Open and Display are lit-up for a second and then grey out. Again, this only happens when on a Thread.

Another thing to note is that when I break on any of the lines of code above in the Thread and inspect the objects I get an error "The function evaluation requires all threads to run". I would think this is more an issue with Visual Studio and the implicit evaluation settings so it should not affect arcmap and it certainly should not cause it to crash. But I thought I would mention it.

Thanks for any help.

1
1

Thanks for the tip Petr, that link was very useful. I am working with TPL not ThreadPool but the problem was still the same - my Arc COM objects need to run under STA which my code is not doing. So, I broke it out so the csv is generated on a separate thread and the layer is added afterwords via the UI thread:

private void _ExecuteDataQueryMapping()
{
    ...
    TaskLoader = Task<object>.Factory.StartNew(() =>
    {
        ...

        DataQueryCsvFile CsvFile = new DataQueryCsvFile();

        //Proceed with CSV save only
        CsvFile.DataTable = table;
        CsvFile.SaveFile();

        return CsvFile;
    });

    TaskLoader.ContinueWith(antecendant => _ExecuteDataQueryMappingComplete((DataQueryCsvFile)antecendant.Result),
        TaskCanceller.Token,
        TaskContinuationOptions.NotOnFaulted,
        TaskScheduler.FromCurrentSynchronizationContext());

}

private void _ExecuteDataQueryMappingComplete(DataQueryCsvFile CsvFile)
{
    ...
    IMxDocument Mxd = (IMxDocument)ExtensionApplicationHook.Document;
    CsvFile.MxDocument = Mxd;
    ISpatialReferenceFactory3 SpatialReferenceFactory = new SpatialReferenceEnvironmentClass();
    CsvFile.SpatialReference = SpatialReferenceFactory.CreateSpatialReference(DataQueryHolder.SpatialReferenceFactoryCode);

    //Put the layer in ArcMap using the UI thread
    CsvFile.MapFile(ToolkitDataset.LocXField, ToolkitDataset.LocYField);

    ...
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.