使用服务结构时出现 System.Runtime.InteropServices.COMException

Posted

技术标签:

【中文标题】使用服务结构时出现 System.Runtime.InteropServices.COMException【英文标题】:System.Runtime.InteropServices.COMException while using service fabric 【发布时间】:2018-02-13 18:02:59 【问题描述】:

我正在 Azure Service Fabric Web API 中创建应用程序,但遇到以下问题:

例外:

System.Runtime.InteropServices.COMException occurred
  ErrorCode=-2146233628
  HResult=-2146233628
  Message=Field of ByRef type. (Exception from HRESULT: 0x801312E4)
  Source=mscorlib
  StackTrace:
       at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
       at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
       at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
       at Microsoft.ServiceFabric.Services.Remoting.Builder.MethodBodyTypesBuilder.BuildRequestBodyType(ICodeBuilderNames codeBuilderNames, CodeBuilderContext context, MethodDescription methodDescription)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.MethodBodyTypesBuilder.Build(ICodeBuilderNames codeBuilderNames, CodeBuilderContext context, MethodDescription methodDescription)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.MethodBodyTypesBuilder.Build(InterfaceDescription interfaceDescription)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.CodeBuilder.Microsoft.ServiceFabric.Services.Remoting.Builder.ICodeBuilder.GetOrBuildMethodBodyTypes(Type interfaceType)
       at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.ProxyGeneratorBuilder`2.Build(Type proxyInterfaceType, IEnumerable`1 interfaceDescriptions)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.CodeBuilder.Microsoft.ServiceFabric.Services.Remoting.Builder.ICodeBuilder.GetOrBuildProxyGenerator(Type interfaceType)
       at Microsoft.ServiceFabric.Services.Remoting.Builder.ServiceCodeBuilder.GetOrCreateProxyGenerator(Type serviceInterfaceType)
       at Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory.CreateServiceProxy[TServiceInterface](Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector, String listenerName)
       at Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy.Create[TServiceInterface](Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector, String listenerName)
       at WebService.Controllers.HomeController.<GetAsync>d__0.MoveNext() in C:\Users\shkulka\Documents\Visual Studio 2015\Projects\SortingApp\WebService\Controllers\HomeController.cs:line 17
  InnerException: 

发生异常的行:

    IRequestManagerService proxy = ServiceProxy.Create<IRequestManagerService>(new Uri("fabric:/SortingApp/RequestManagerService"));

一些代码供参考:

namespace WebService.Controllers

    [Route("api/[controller]")]
    public class HomeController : Controller 
    
        [HttpGet]
        public async Task<IActionResult> GetAsync(int opId, string sortType = "Quick", string guid="454", string commaSeperatedArray="1,2,3,4")
        
            IRequestManagerService proxy = ServiceProxy.Create<IRequestManagerService>(new Uri("fabric:/SortingApp/RequestManagerService"));
           //rest of the code continues . . . 

当我点击以下 URL 时发生异常:

http://localhost:8792/api/home?opId=0&sortType=Quick&guid=12&commaSeperatedArray=1,2,3,4

我正在以管理员权限运行我的项目。整个解决方案的平台目标是 x64。

如何摆脱异常?


更新 1:

在点击 URL 之前,我可以观察以下有关服务结构的信息。

在服务结构资源管理器中:

在诊断事件窗口中:

    
  "Timestamp": "2017-09-06T10:49:34.7442479+05:30",
  "ProviderName": "Microsoft-ServiceFabric-Services",
  "Id": 2,
  "Message": "RunAsync has been cancelled for a stateful service replica.  The cancellation will be considered 'slow' if RunAsync does not halt execution within 4000 milliseconds.  Application Type Name: GettingStartedApplicationType, Application Name: fabric:/GettingStartedApplication, Service Type Name: MyActorServiceType, Service Name: fabric:/GettingStartedApplication/MyActorService, Partition Id: 097c837b-857e-4f10-8c3a-8a902c1f0bb6, Replica Id: 131491461074099453",
  "ProcessId": 34840,
  "Level": "Informational",
  "Keywords": "0x0000F00000000000",
  "EventName": "StatefulRunAsyncCancellation",
  "ActivityID": null,
  "RelatedActivityID": null,
  "Payload": 
    "applicationTypeName": "GettingStartedApplicationType",
    "applicationName": "fabric:/GettingStartedApplication",
    "serviceTypeName": "MyActorServiceType",
    "serviceName": "fabric:/GettingStartedApplication/MyActorService",
    "partitionId": "097c837b-857e-4f10-8c3a-8a902c1f0bb6",
    "replicaId": 131491461074099453,
    "slowCancellationTimeMillis": 4000.0
  



  "Timestamp": "2017-09-06T10:49:34.760793+05:30",
  "ProviderName": "Microsoft-ServiceFabric-Services",
  "Id": 2,
  "Message": "RunAsync has been cancelled for a stateful service replica.  The cancellation will be considered 'slow' if RunAsync does not halt execution within 4000 milliseconds.  Application Type Name: GettingStartedApplicationType, Application Name: fabric:/GettingStartedApplication, Service Type Name: MyActorServiceType, Service Name: fabric:/GettingStartedApplication/MyActorService, Partition Id: 78f9a969-4f09-4d8b-932f-4962cce7f4cd, Replica Id: 131491461074094464",
  "ProcessId": 27832,
  "Level": "Informational",
  "Keywords": "0x0000F00000000000",
  "EventName": "StatefulRunAsyncCancellation",
  "ActivityID": null,
  "RelatedActivityID": null,
  "Payload": 
    "applicationTypeName": "GettingStartedApplicationType",
    "applicationName": "fabric:/GettingStartedApplication",
    "serviceTypeName": "MyActorServiceType",
    "serviceName": "fabric:/GettingStartedApplication/MyActorService",
    "partitionId": "78f9a969-4f09-4d8b-932f-4962cce7f4cd",
    "replicaId": 131491461074094464,
    "slowCancellationTimeMillis": 4000.0
  

点击网址后:


更新 2:

界面:

namespace RequestManagerService.Interfaces

    public interface IRequestManagerService : IService
    
        Task submitSortRequest(string sortType, string guid, string commaSeperatedArray);
        Task<bool> isSortingComplete(string guid);
        Task<string> getSortedArray(string guid);
        Task<bool> isSortRequested(string sortType, ref string commaSeperatedArray, ref string guid);
        Task setSortResult(string sortType, string guid, string sortedArray);
    

接口实现:

namespace RequestManagerService

    /// <summary>
    /// An instance of this class is created for each service instance by the Service Fabric runtime.
    /// </summary>
    internal sealed class RequestManagerService : StatelessService, IRequestManagerService
    
        // <guid,<sorttype, array, isSortComplete>>
        Dictionary<string, Tuple<string, string, bool>> SortDictionary = new Dictionary<string, Tuple<string, string, bool>>(); 
        public RequestManagerService(StatelessServiceContext context)
            : base(context)
        

        

        public async Task<string> getSortedArray(string guid)
        
            Tuple<string, string, bool> tempTuple;
            string sortedArray= "";

            if (await isSortingComplete(guid))
            
                SortDictionary.TryGetValue(guid, out tempTuple);
                sortedArray = tempTuple.Item2;
            
            else
            
                sortedArray = "Either there no request with this guid or the sorting is not yet complete.";
            
            return sortedArray;
        

        public Task<bool> isSortingComplete(string guid)
        
            bool isSortComplete = false;
            Tuple<string, string, bool> tempTuple;

            if (SortDictionary.ContainsKey(guid)) 
                SortDictionary.TryGetValue(guid, out tempTuple);
                isSortComplete = tempTuple.Item3;
            

            return Task.FromResult(isSortComplete);
        

        public Task<bool> isSortRequested(string sortType, ref string commaSeperatedArray, ref string guid)
        
            bool requestFound = false;

            foreach(KeyValuePair<string, Tuple<string, string, bool>> entry in SortDictionary)
            
                if (entry.Value.Item1 == sortType && entry.Value.Item3 == false)
                
                    commaSeperatedArray = entry.Value.Item2;
                    guid = entry.Key;
                    requestFound = true;
                    break;
                
            

            return Task.FromResult(requestFound);
        

        public Task setSortResult(string sortType, string guid, string sortedArray)
        
            if (SortDictionary.ContainsKey(guid))
            
                Tuple<string, string, bool> updatedTuple = new Tuple<string, string, bool>(sortType, sortedArray, true);
                SortDictionary[guid] = updatedTuple;
            
            return Task.FromResult<object>(null);
        

        public Task submitSortRequest(string sortType, string guid, string commaSeperatedArray)
        
            Tuple<string, string, bool> tuple = new Tuple<string, string, bool>(sortType, commaSeperatedArray, false);
            SortDictionary.Add(guid, tuple);
            return Task.FromResult<object>(null);
        

        /// <summary>
        /// Optional override to create listeners (e.g., TCP, HTTP) for this service replica to handle client or user requests.
        /// </summary>
        /// <returns>A collection of listeners.</returns>
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        
            return new ServiceInstanceListener[1] 
                new ServiceInstanceListener(this.CreateServiceRemotingListener)
            ;
        

        /// <summary>
        /// This is the main entry point for your service instance.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service instance.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        
            // TODO: Replace the following sample code with your own logic 
            //       or remove this RunAsync override if it's not needed in your service.

            long iterations = 0;

            while (true)
            
                cancellationToken.ThrowIfCancellationRequested();

                ServiceEventSource.Current.ServiceMessage(this.Context, "Working-0", ++iterations);

                await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
            
        
    

【问题讨论】:

您能否分享一下您尝试访问的服务的合同实现? @KirylZ:嘿,刚刚添加了接口及其实现。如果您有任何想法,请告诉我。 我想说这里的合约不支持 ref/out 参数。摆脱它们,然后重试。 我也想过。但是在控件到达包含refout 的语句之前发生异常。但我会尝试不使用它们。 这会发生在方法调用之前,因为整个类型需要首先在内存中构建。 【参考方案1】:

我想说这里的合同不支持 ref/out 参数。理想情况下,您的服务联系人不应依赖于特定语言的工件。摆脱它们,一切都会正常。

【讨论】:

非常感谢!如果可能的话,请指出合同中不支持提及 ref/out 参数的一些资源。我很想阅读更多内容。 不客气。我记得整个 SF 文档中唯一的参考是https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-actors-get-started。您会在此处找到“Actor 接口方法不得具有 out、ref 或可选参数。”。 我知道在 WCF 中可以使用 ref 参数定义合约,但返回类型必须为“void”。由于使用 SF 远程侦听器,您的方法必须是返回任务的异步方法,这可能是阻止您使用 ref 参数的原因。 遗漏一些细节会浪费很多时间!非常感谢。

以上是关于使用服务结构时出现 System.Runtime.InteropServices.COMException的主要内容,如果未能解决你的问题,请参考以下文章

WPF 拖动时出现 Invalid FORMATETC structure

无法加载文件或程序集“System.Runtime.CompilerServices.Unsafe”

使用谓词列表时出现 DataContract SerializationException

部署 Azure 函数时无法从程序集“System.Runtime”加载类型“System.IO.Path”

无法安装 Nuget 包

为柴油模型定义结构时出现错误未定义类型或模块