перетащите в другой процесс

Я пытаюсь вытащить объект в проводник.
Объект должен привести к загрузке файла, таким образом, я использовал пример, я нашел в сети для загрузки файла с помощью a CustomDataObject это называет событие, когда ему на самом деле нужен поток, и затем мое приложение делает тяжелый подъем и выполняет загрузку.
Это работало просто великолепно в подобной операции Буфера обмена.

Фактическая загрузка файла также вызывает некоторые изменения UI в моем приложении. Главным образом "рабочий" значок, изменяющийся на форме и также раскрывающемся воздушном шаре в случае ошибки.

В операции буфера обмена я просто использовал InvokeRequired и BeginInvoke при необходимости, для проверки те изменения UI происходят на основном потоке. В операции перетаскивания поток UI ожидает возврата из DoDragDrop, в то время как событие, повышаемое CustomDataObject называется на другом потоке. Когда я пытаюсь звонить BeginInvoke или Invoke поток UI все еще ожидает, и я не могу закончить отбрасывание.

Разве существует ли некоторый образец или рекомендуемая лучшая практика, о том, как позволить перекрестное приложение, перетаскивают отбрасывание n, при доступе к UI исходного приложения?

ОБНОВЛЕНИЕ

вот исходная статья CodeProject с DataObjectEx Я изменил для своего собственного использования. Я просто изменился GetFileContents метод для вызова виртуального метода, который возвращает a Stream содержа данные файла, наследованные от класса и переопределенные, что виртуальный метод для получения файла от сети. Проблема возникла, когда я хотел изменить материал в UI при получении файла. Как я сказал ранее - основной поток UI все еще застревает в DoDragDrop вызов метода, таким образом, я не могу вызвать его вовремя, чтобы сделать изменения UI, необходимые рабочему потоку прежде и после загрузки файла.

9
задан Noam Gal 11 January 2010 в 15:31
поделиться

2 ответа

Чтобы выяснить, что люди говорят о DoEvents, вот описание того, что может произойти.

Предположим, что у вас есть форма с данными о ней, и ваше продолжительное событие сохраняет ее в базе данных или создает на ее основе отчет. Вы начинаете сохранять или генерировать отчет, а затем периодически вызываете DoEvents, чтобы экран продолжал рисовать.

К сожалению, экран не только картина, но и реагирует на действия пользователя. Это происходит потому, что DoEvents останавливает то, что вы делаете сейчас для обработки всех сообщений Windows, ожидающих обработки приложением Winforms. Эти сообщения включают запросы на перерисовку, а также любой пользователь, набирающий, щелкающий и т.д.

Так, например, во время сохранения данных пользователь может выполнять такие действия, как создание модального диалогового окна приложения, которое полностью не связано с длительной выполняемой задачей (например, Справка - > О программе). Теперь вы реагируете на новые действия пользователя внутри уже выполняющейся длинной задачи. DoEvents будет возвращен, когда все события, которые ожидали, когда вы его вызвали, будут завершены, а затем ваша долгая задача будет продолжена.

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

Здесь происходит то, что Application.DoEvents делает ваш код повторным. См. определение википедии здесь . Обратите внимание на некоторые точки в верхней части статьи, что для повторного ввода кода он:

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

Маловероятно, что длинный код в приложении WinForms работает только с данными, передаваемыми в метод вызывающей стороной, не содержит статических данных, не содержит блокировок и вызывает только другие методы.

Как говорят многие люди, DoEvents может привести к очень странным сценариям в коде. Ошибки, к которым это может привести может быть очень трудно диагностировать, и ваш пользователь вряд ли скажет вам «О, это могло произойти, потому что я нажал эту несвязанную кнопку, пока я ожидал ее сохранения».

-121--3236074-

Поскольку вы используете значение строки в столбце, я предполагаю, что вы пытаетесь задать его перед созданием объекта? Я думаю, вы хотели сделать его статической переменной класса вместо переменной экземпляра.

-121--1699273-

У меня была та же проблема, и я обнаружил, что System.Windows.Forms.Control.DoDragDrop проигнорировал реализацию IAsyncOperation моей формы, вместо того, чтобы использовать реализацию DataObject WinForm IDataObject внутри.К сожалению, класс DataObject WinForm не реализует IAsyncOperation.

Поэтому я использовал реализацию проекта VirtureFileDataObject для IAsyncOperation, IDataObject, вызвав VirtityFileDataObject.DoDragDrop вместо Control.DoDragDrop. Я устанавливаю VirtureFileDataObject.FileDescriptor.StreamContents в делегат, где я вызываю в поток пользовательского интерфейса, чтобы сообщить о ходе загрузки файла.

1
ответ дан 5 December 2019 в 02:07
поделиться

Если это - стандартное применение WinForms, то все, что действительно необходимо сделать в заявлении, должно добавить обработчики событий в Форме для DragEnter и DragDrop.

Внутренняя часть DragEnter, вы захотите проверить тип объекта удостовериться, что это - имя файла:

private void MyForm_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
        if (files != null)
        {
            // Do additional checks here if needed, like check extensions
            e.Effect = DragDropEffects.Copy;
            return;
        }
    }

    e.Effect = DragDropEffects.None;
}

Затем в вашем обработчике DragDrop, я просто сохранил бы от имен файлов и затем активировал бы таймер. Это позволяет DragDrop сразу возвратиться, так, чтобы другое приложение (в вашем примере, Windows Explorer) не зависало, в то время как вы делаете любую обработку на файле, который может занять время. Источник Перетаскивания не возвратится , пока DragDrop не закончится.

private void MyForm_DragDrop(object sender, DragEventArgs e)
{
    string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
    if (files != null)
    {
        _filesToProcess.Text = files[0];  // Assuming this is declared at the Form level

        // Schedule a timer to fire in a few miliseconds as a simple asynchronous method
        _DragDropTimer.Interval = 50;
        _DragDropTimer.Enabled = true;
        _DragDropTimer.Start();
        Activate();  // Activates the form and gives it focus
    }
}
1
ответ дан 5 December 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: