gpt4 book ai didi

c# - WCF 服务,由于传入流的 "Unexpected end of file"引发流异常

转载 作者:行者123 更新时间:2023-11-30 21:13:46 47 4
gpt4 key购买 nike

我编写了一个交换传输代理,用于将电子邮件正文上传到 WCF 服务。该服务与 Exchange 位于同一个盒子上,监听 localhost:1530 以接收传入的 TCP 连接。传输代理使用 .NET 3.5 Framework 实现,服务在 .NET 4.0 Framework 上实现的 Windows 服务中自托管。

我的问题:为什么流在读取完成之前终止,我该如何解决?

服务契约定义如下:

[ServiceContract]
public interface IReceiveService
{
[OperationContract]
Guid ImportMessage(DateTime dateTimeReceived, string from, IList<string> to, string subject, int attachmentCount, bool bodyEmpty, Guid clientID);

[OperationContract]
void ImportMessageBody(IMessageBody body);

[OperationContract]
void ImportMessageAttachment(IMessageAttachment attachment);
}

更新:我重新订购了它,以便其他人更容易快速阅读问题,而不必阅读我的描述的其余部分,这些描述很长。这第一位展示了我如何启动 Task 来处理请求似乎是问题所在。实际上,如果我注释掉 Task.Factory.StartNew() 部分,Stream.CopyTo 就可以工作。

在我的服务实现中,我尝试使用 Stream.CopyTo 将传入流复制到临时文件,如下所示:

public void ImportMessageBody(IMessageBody body)
{
Task.Factory.StartNew(() =>
{
string fileName = GetFileNameFromMagicalPlace();
using (FileStream fs = new FileStream(fileName, FileMode.Append))
{
body.Data.CopyTo(fs); // <---- throws System.IOException right here
}
});
}

异常错误为:“错误:读取流时抛出异常。”堆栈跟踪:

   at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.Read(Byte[] buffer, Int32 offset, Int32 count) 
at System.IO.Stream.CopyTo...

有一个内部异常:

System.Xml.XmlException: Unexpected end of file. Following elements are not closed: Address, IMessageBody, Body, Envelope. 
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlBufferReader.GetByteHard()
at System.Xml.XmlBufferReader.ReadMultiByteUInt31()
at System.Xml.XmlBinaryReader.ReadName(StringHandle handle)
at System.Xml.XmlBinaryReader.ReadNode()
at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.Read(Byte[] buffer, Int32 offset, Int32 count)

其他细节如下。


IMessageBody 定义如下:

[MessageContract]
public class IMessageBody
{
[MessageHeader]
public Guid MessageID { get; set; }

[MessageHeader]
public string Format { get; set; }

[MessageBodyMember]
public System.IO.Stream Data { get; set; }
}

显示相关位的传输代理的缩写版本(我希望):

public class Agent : RoutingAgent
{
public delegate void PostingDelegate(MailItem item);
IReceiveService service;

public Agent()
{
string tcpServiceUri = "net.tcp://localhost:1530";

NetTcpBinding endpointBinding = new NetTcpBinding();
endpointBinding.TransferMode = TransferMode.Streamed;

ServiceEndpoint serviceEndpoint = new ServiceEndpoint(
ContractDescription.GetContract(typeof(IReceiveService)),
endpointBinding,
new EndpointAddress(tcpServiceUri));
ChannelFactory<IReceiveService> factory = new ChannelFactory<IReceiveService>(serviceEndpoint);
service = factory.CreateChannel();

this.OnSubmittedMessage += new SubmittedMessageEventHandler(Agent_OnSubmittedMessage);
}

void Agent_OnSubmittedMessage(SubmittedMessageEventSource source, QueuedMessageEventArgs e)
{
if (TheseAreTheDroidsImLookingFor(e))
{
PostingDelegate del = PostData;
del.BeginInvoke(e.MailItem, CompletePost, GetAgentAsyncContext());
}
}

void PostData(MailItem item)
{
// Body class is basically direct implementation of IMessageBody
// with a constructor to set up the public properties from MailItem.
var body = new Body(item);
service.ImportMessageBody(body);
}

void CompletePost(IAsyncResult ar)
{
var context = ar.AsyncState as AgentAsyncContext;
context.Complete();
}
}

最后,服务实现是这样托管的:

string queueUri = String.Format("net.tcp://localhost:{0}/{1}", port, serviceName);
try
{
host = new ServiceHost(typeof(ReceiveService), new Uri(queueUri));
host.AddDefaultEndpoints();
var endpoint = host.Description.Endpoints.First();
((NetTcpBinding)endpoint.Binding).TransferMode = TransferMode.Streamed;

trace.Log(Level.Debug,String.Format("Created service host: {0}", host));

host.Open();
trace.Log(Level.Debug,"Opened service host.");
}
catch (Exception e)
{
string message = String.Format("Threw exception while attempting to create ServiceHost for {0}:{1}\n{2}", queueUri, e.Message, e.StackTrace);
trace.Log(Level.Debug,message);
trace.Log(Level.Error, message);
}

最佳答案

嗯,代码太多了。您应该尝试将代码最小化为尽可能小的可重现示例。我想问题可能出在这里:

public void ImportMessageBody(IMessageBody body)
{
Task.Factory.StartNew(() =>
{
string fileName = GetFileNameFromMagicalPlace();
using (FileStream fs = new FileStream(fileName, FileMode.Append))
{
body.Data.CopyTo(fs); // <---- throws System.IOException right here
}
});
}

默认情况下应用OperationBehavior 此行为包含默认设置为 true 的 AutoDisposeParameter disposes all disposable parameters当操作结束时。所以我希望该操作在您的 Task 能够处理整个流之前结束。

关于c# - WCF 服务,由于传入流的 "Unexpected end of file"引发流异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6680558/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com