Передача нескольких потоков в WCF - PullRequest
3 голосов
/ 05 октября 2009

Что у меня есть?

У меня есть контракт WCF, который принимает объект Stream.

Что мне нужно?

Я хочу преобразовать контракт для приема нескольких потоков. Но есть некоторая проблема с передачей нескольких потоков в WCF. Теперь у меня есть два варианта,

(1) Многократный вызов метода WCF

(2) Изменить контракт, чтобы принимать двумерный байтовый массив со всем содержимым файла

Может кто-нибудь сказать мне, какой вариант лучше?

Заранее спасибо!

Ответы [ 4 ]

8 голосов
/ 07 октября 2009

Мы решили эту проблему, построив реализацию обертки Stream на клиенте, которая объединяет список потоков вместе, от начала до конца (например, .Read делегатов в первый поток - когда он достигает EOF в потоке 1, он начинает чтение потока 2 и тд). У него есть свойство метаданных, которое содержит имена потоков и их позиции, которые мы включаем в вызов в атрибуте [MessageHeader], который сообщает, что находится в потоке, и смещения каждого (клиентские потоки должны поддерживать .Length). Потребитель потоков на сервере знает, как прочитать этот объект метаданных и вывести список потоков по порядку. Единственное ограничение заключается в том, что они должны быть обработаны по порядку. Отлично работает!

4 голосов
/ 05 октября 2009

В WCF вы не можете иметь несколько параметров потока в одном методе службы. Это просто системное ограничение.

См. документацию MSDN о потоковой передаче WCF :

Ограничения на потоковые передачи

Использование режима потоковой передачи заставляет время выполнения применять дополнительные ограничения.

Операции, которые происходят через Потоковый транспорт может иметь контракт с не более одного входа или выхода параметр. Этот параметр соответствует на весь текст сообщения и должно быть Сообщение, производный тип Stream или IXmlSerializable реализация. Имея возвращаемое значение для операции эквивалентно с выходным параметром.

Итак, на данный момент все, что вы можете сделать, это вызвать ваш метод несколько раз.

Марк

1 голос
/ 19 марта 2013

В моей системе мне нужно отправить FileStream и общий список пользовательских данных в службу WCF. Вот как я делаю это, чтобы объединить оба в один поток и отправить его службе, которая возвращает поток результатов клиенту:

Договор на обслуживание:

[ServiceContract]
[XmlSerializerFormat]
public interface IMyService
{
    [OperationContract]
    ResultClass MyOperation(Parameters param);
}

Обратный поток:

[MessageContract]
public class ResultClass
{
    [MessageBodyMember]
    public System.IO.Stream Stream { get; set; }
}

Входной поток:

[MessageContract]
public class Parameters
{
    [MessageHeader]
    public long Length1 { get; set;}
    [MessageHeader]
    public long Length12 { get; set;}
    [MessageBodyMember]
    public Stream Stream { get; set;}
}

У клиента WCF:

public static void BuildStream(string filePath, List<CustomData> otherParams, ref Parameters param)
{
        BinaryFormatter formatter = new BinaryFormatter();
        FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        MemoryStream allStreams = new MemoryStream();
        MemoryStream dataStream = new MemoryStream();
        formatter.Serialize(dataStream, otherParams);
        dataStream.Seek(0, SeekOrigin.Begin);
        fs.Seek(0, SeekOrigin.Begin);
        fs.CopyTo(allStreams);
        dataStream.CopyTo(allStreams);
        param.TemplateLength = fs.Length;
        param.DataLength = dataStream.Length;
        param.Stream = allStreams;
        param.Stream.Seek(0, SeekOrigin.Begin);
}

В реализации сервиса вытащите первый и второй потоки из объединенного потока:

List<CustomData> dataSheets;
using (MemoryStream ms = new MemoryStream())
{
    MemoryStream dataStream;
    BinaryFormatter formatter = new BinaryFormatter();
    byte[] templatebuffer, databuffer;
    filebuffer = new byte[m_param.Length1];
    databuffer = new byte[m_param.Length2];
    // Get the whole stream
    m_param.Stream.CopyTo(ms);
    ms.Seek(0, SeekOrigin.Begin);
    // Get the first stream
    ms.Read(templatebuffer, 0, (int)m_param.TemplateLength);
    // Get the custom data
    ms.Read(databuffer, 0, (int)m_param.DataLength);
    using (dataStream = new MemoryStream(databuffer))
    {
        dataStream.Seek(0, SeekOrigin.Begin);
        dataSheets = (List<DataSheet>) formatter.Deserialize(dataStream);
        m_param.Stream.Close();
    ...
0 голосов
/ 05 октября 2009

Вы можете рассмотреть MTOM привязку и иметь контракт данных с несколькими byte[] свойствами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...