2013-11-25 5 views
3

Я работаю над многопоточным приложением, и мне приходится сталкиваться с проблемой использования буфера обмена (я работаю с API Qlikview - и мне нужно скопировать таблицы в excel), и проблема в том, что я думаю, что произойдет что-то вроде этого: В потоке # 1 я открываю документ QW и копирую таблицу, и до того, как я получу ее вставить на листе excel, идет поток # 2 и использует буфер обмена скопируйте таблицу из своего документа. Мне любопытно, можно ли даже использовать буфер обмена из многопоточного приложения? Я читал всевозможные вещи об использовании буфера обмена, и единственная ясная вещь, о которой я это понимал, заключается в том, что метод должен быть STA (?). Поэтому я сейчас немного смущен. СпасибоC# Многопоточное приложение, использующее буфер обмена

+0

Вы пробовали? у вас есть ошибка? пожалуйста, отправьте код –

+0

. Я бы не стал использовать буфер обмена таким образом, если возможно. Нет ли способа использовать Qlikview API для вывода данных без буфера обмена? Если это так, вы можете определенно использовать автоматические прерывания Excel для непосредственного вставки данных в лист без обращения к буферу. – Baldrick

+0

Я ограничен тем, что API предоставляет для экспорта. В настоящее время я экспортирую все таблицы в виде xml-файлов, а затем планирую их десериализацию в datatables .. затем работать с openXML для создания excel. казалось довольно сложным планом, пока я не понял, что с помощью этого метода я не просто теряю форму, но, кажется, я теряю важные строки и столбцы (для сложных таблиц с rowspans и colspans). qlikview не предоставляет точные XML-файлы после экспорта. Он также имеет экспорт в Excel, но без возможностей шаблонов и отсутствие возможности экспортировать несколько таблиц в один файл Excel – Vlad

ответ

3

Поскольку буфер обмена является общим ресурсом, вам нужно быть очень осторожным. Вполне вероятно, что операция в thread1 будет вытеснена thread2. Вы должны иметь возможность использовать критические разделы, чтобы обойти это, но ... вам нужно учитывать, что другие приложения в системе также задействованы, как это трудно предсказать. Другие слушатели буфера обмена будут делать свою работу, возможно вставляя данные в себя или открывая буфер обмена, чтобы «заглянуть» в содержимое. Это затруднит ваши попытки быстро скопировать/вставить данные, так как вам, вероятно, придется подождать 1000 мс или около того после копирования, прежде чем вы сможете надежно вставить его. Вам нужно подумать о том, что произойдет, если пользователь работает с расширителем буфера обмена (вы будете заполнять его своим дерьмом). Как насчет удаленного рабочего стола? Вам придется дождаться синхронизации буфера обмена по сети, что в некоторых случаях означает, что у вас может быть еще один набор приложений для мониторинга буфера обмена, которые хотят изучить ваши данные буфера обмена, прежде чем вы сможете вставить его.

Затем рассмотрите тот факт, что буфер обмена предназначен для удобства пользователя, а не как костыль для программиста.

Если вы продолжите путь по этому пути, вы наверняка обречены. Это плохая идея и невозможно реализовать без причинения сопутствующего ущерба. Вы должны подумать о своем дизайне. И нет, у меня нет лучших идей.

+1

Спасибо, Крис, вы выделили некоторые очень хорошие моменты. И нет, я еще не начал с этого, так как я ожидал, что это будет невозможно, хотя я не понял всех последствий. Хорошего дня! – Vlad

3

Ну, с помощью многопоточности вы можете блокировать части кода, которые может работать только один поток одновременно. Обычно это делается для блокировки ресурсов, к которым невозможно одновременно получить доступ (например, пример вашего буфера обмена).

определяются следующим образом (в данном примере private, так что было бы в классе, где вы хотите поместить свой замок):

private readonly System.Object MyLock = new System.Object(); 

И затем использовать

lock (MyLock) 
{ 
    // Locked Code 
} 

Теперь нет более чем один поток может запускать код внутри блокировки.

Примечание: в вашем случае это может вызвать проблемы, если другие приложения/пользователи начнут использовать буфер обмена. Если возможно, вы можете захотеть использовать что-то отличное от буфера обмена.

MSDN Thread Synchronization

0

я столкнулась с такой же вопрос несколько дней назад при работе на конкретной автоматизации. Мне удалось преодолеть это, заблокировав процессы при использовании объекта ClipBoard, поэтому, если первый поток должен использовать ClipBoard, другим придется ждать завершения процесса. Таким образом, мы можем гарантировать, что мы не получим неправильного поведения во время вставки данных где-нибудь, так как на этом ресурсе не будет конфликта.

Итак, мой подход состоял в том, чтобы создать управляющую переменную в среде (Environment.SetEnvironmentVariable) с именем «CLIPBOARD_INUSE» и установить ее в true, когда конкретный поток должен выполнять методы ClipBoard. В других потоках цикл while проверяет, является ли переменная «CLIPBOARD_INUSE» ложной (ресурс доступен) (используйте снова Thread.Sleep()). Когда первый поток заканчивается с использованием ClipBoard, пришло время освободить ресурс, установив контрольную переменную, которую мы создали, назад к false, поэтому следующий поток, требующий ClipBoard, может его использовать.

Надеюсь, вы найдете это решение полезным, как я.

С уважением,

Bruno Costa.

Смежные вопросы