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

Calling WCF Service in Multithreading Environment that has 2 different .SVC Files. Error while calling both service at the same time

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

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

      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 服务。 我们也在这里有锁。我不确定如何准确解决此错误?

谢谢, 丽塔

使用lock (new object())每次都会创建一个新对象。这意味着每个线程锁定在不同的对象上。这根本不是锁定。

如果您的两个服务不使用相同的资源,则不需要锁定。 但正如我从您的例外情况中看到的那样,您在两种服务之间使用共享资源 - 即 Entity framework DbContext。

我假设一个线程正在初始化 DbContext,同时第二个线程正在使用相同的 DbContext。从异常消息中可以看出:

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.

更好的锁定是:

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;
                    }
                }
            }