Асинхронные данные TCP из другого потока не могут быть безопасными.Перекрестная операция - PullRequest
0 голосов
/ 15 мая 2011

У меня есть две библиотеки классов. Одна - это обычная сборка .NET, а другая - сборка устройства Compact Framework, связывающая файлы классов рабочего стола. Эта библиотека отвечает за асинхронные операции TCP между сервером и клиентом.

Теперь я создаю проект Windows для сервера и проект устройства Windows Mobile Forms в качестве клиента.

Я использую некоторые события для данных, полученных для клиента и сервера. Для запуска данных, полученных из ASync, полученных через TCP safe, я использую фиктивный класс Control, чтобы проверить, требуется ли Invoke.

Странно то, что при отправке данных с сервера клиенту устройства CF данные не нуждаются в какой-либо обработке потоков для элементов управления, где вам нужно показывать данные. Но при отправке данных с клиента на сервер я получаю исключение операции с несколькими потоками.

Вот код.

Статический метод, который я использую для защиты данных.

public static void InvokeIfNecessary(Control control, Action setValue)
{
    if (control.InvokeRequired)
    {
        control.Invoke(setValue);
    }
    else
    {
        setValue();
    }
}

Когда я хочу выбросить данные, полученные из TCP-соединения.

    if (OnClientChangeConnection != null) SafeData.InvokeIfNecessary(_helpControl, () => OnClientChangeConnection(ConnectedClients, requestClientInfo));

Есть идеи, почему у меня такое поведение? Или лучше справиться с этой проблемой?

Спасибо!

1 Ответ

1 голос
/ 16 мая 2011

Поскольку вы определяете InvokeIfNecessary, обратите внимание на часть «при необходимости».Это означает, что запрос может поступить в другом потоке от диспетчера.Заметьте, я говорю «может» - это означает, что это может и не происходить, и поэтому может исходить от диспетчера.

Полная структура и компактная структура могут по-разному использовать многопоточность для обработки асинхронных операций.Например, компактный каркас может быть однопоточным (поскольку он работает на мобильном устройстве), тогда как полноценный каркас сервера может быть многопоточным.API выглядит одинаково, но данные могут поступать из разных потоков.

Один хороший пример - Silverlight, который использует поток диспетчера (т. Е. Основной поток пользовательского интерфейса) для доступа к сети и прочего, даже если выиспользуя асинхронные вызовы BeginXXX / EndXXX.Поэтому, если вы выполните упрощенный код в этой мобильной среде, вы не получите исключение потока, но вы определенно можете получить его на сервере, где вызовы BeginXXX / EndXXX могут идти в разные потоки -опять же, они не могут, и это действительно зависит от решения сервера во время вызова.

Следовательно, вам всегда нужно выяснить, может ли запрос поступить из другого потока.Использование чего-то вроде вашего InvokeIfNecessary является необходимым злом и является правильным поступком - не опускайте его только потому, что в некоторых средах вы не видите проблемы.

...