在具有2个不同.SVC文件的多线程环境中调用WCF服务。同时调用两个服务时出错

时间:2018-06-07 19:22:35

标签: c# asp.net-mvc multithreading wcf visual-studio-2015

我有一个应用程序,它有两个特定于两个不同模块的.SVC文件。 在现有的Application中,我们在同一个线程中一个接一个地调用。我从未遇到过问题。

作为重构的一部分,我清理了他们从两个不同的线程调用它们的那些服务(第一个线程调用第一个方法,第二个线程调用第二个方法)。这两种方法甚至不同。有时代码执行没有任何问题。但有时,我收到以下错误,说无法找到实例。同样,这个错误并不总是发生。

      Exception:
                RMS Conversion failed : System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: ComponentActivator: 

could not instantiate Axis.Edc.Service.RMS.RMSConversionService (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
    Castle.MicroKernel.ComponentActivator.ComponentActivatorException: ComponentActivator: could not instantiate RMS.RMSConversionService ----> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ----> System.InvalidOperationException: The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
       at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
       at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
       at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
       at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator...).

以下是对服务的代码调用:

public EnumConversionStatus GenerateRmsImportFiles(int submissionId)
        {
            lock (new object())
            {
                using (var client = new RMSConversionService.RMSConversionServiceClient())
                {
                    var result = client.GenerateRmsImportFiles(submissionId);
                    client.Close();
                    return result;
                }
            }
        }


public EnumConversionStatus GenerateAirImportFiles(int submissionId)
        {
            lock (new object())
            {
                using (var client = new AIRConversionService.AirConversionServiceClient())
                {
                    var result = client.GenerateAirImportFiles(submissionId);
                    return result;
                }
            }
        }

这里我们有两个不同的端点用于2个不同的SVC服务。 在这里我们还有锁。我不确定如何彻底摆脱这个错误?

谢谢, 丽塔

1 个答案:

答案 0 :(得分:0)

如果您的两项服务不使用相同的资源,则无需锁定。 但正如我从您的异常中看到的那样,您在两个服务之间使用共享资源 - 即Entity框架DbContext。

因为您使用的是错误的锁定技术,所以根本不会锁定。我想一个线程正在初始化DbContext,同时第二个线程使用相同的DbContext。正如您从异常消息中看到的那样:

  

创建模型时无法使用上下文。如果在OnModelCreating方法中使用上下文,或者同时由多个线程访问相同的上下文实例,则可能抛出此异常。请注意,DbContext和相关类的实例成员不保证是线程安全的。

如果您的意思是使用lock来确保线程安全,那么您使用lock命令的方式非常糟糕。

正确的锁定用法是:

private object _lock = new object();

    public EnumConversionStatus GenerateRmsImportFiles(int submissionId)
            {
                lock (_lock)
                {
                    using (var client = new RMSConversionService.RMSConversionServiceClient())
                    {
                        var result = client.GenerateRmsImportFiles(submissionId);
                        client.Close();
                        return result;
                    }
                }
            }


    public EnumConversionStatus GenerateAirImportFiles(int submissionId)
            {
                lock (_lock)
                {
                    using (var client = new AIRConversionService.AirConversionServiceClient())
                    {
                        var result = client.GenerateAirImportFiles(submissionId);
                        return result;
                    }
                }
            }