2016-02-02 3 views
6

Мое приложение имеет простую функцию, где он подключается к Excel и будет выполнять операции перетаскивания между ними. В частности, я просто беру некоторые текстовые значения из своего приложения, перетаскивая их в Excel и отбрасывая их.DragDrop.DoDragDrop не возвращается при выполнении операции пересылки в Excel

Это работает 90% времени, но, как ни странно, в определенное время мое приложение просто зависает. Я прикрепляю отладчик и приостанавливаю выполнение, и он застревает в DragDrop.DoDragDrop - эта функция никогда не возвращается, и мое приложение будет вечно зависеть.

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

Вот код, я использую:

DragDrop.DoDragDrop(sender as DependencyObject, draggable.GetDragDropString(), DragDropEffects.Copy); 

GetDragDropString() это просто функция, которая возвращает строку данных уронить в Excel. sender - это только компонент пользовательского интерфейса, который я перетаскиваю. Как сетка или поле редактирования, текстовое поле и т. Д. Может быть любой из них.

Спасибо за помощь!

EDIT: В некоторых случаях возникает проблема с возвратом DragDrop.DoDragDrop, возможно, кто-то может помочь с написанием правильного тайм-аута? Я пробовал запустить новый Thread и иметь его тайм-аут, который работает в простых случаях и когда работа в потоке не требует ресурсов пользовательского интерфейса. Однако, когда я вызываю DoDragDrop в новый поток с таймаутом, он выдает исключение, говорящий, что поток не может получить доступ к объекту, потому что ему принадлежит другой поток. Поэтому мне нужно вызвать эту функцию в том же потоке. Поэтому по существу мне нужен тайм-аут в потоке пользовательского интерфейса, когда эта функция не может вернуться за определенное время.

+0

@HansPassant спасибо за ответ - Сопротивление всегда выполняется пользователем. Вы говорите, что мне нужно обрабатывать обратные вызовы Excel в моем коде приложения? Как вы назвали вызовы DragEnter/Over/Drop? Я просто предположил, что пользователь перетаскивает данные в сам Excel, после чего функция DoDragDrop вернется. Это работает в 90% случаев, но иногда оно зависает. – ryrich

ответ

1

Я думаю, что следующий должен делать эту работу, но я сломаю его вниз, как я иду вдоль

public class DragDropTimer 
{ 
    private delegate void DoDragDropDelegate(); 
    private System.Timers.Timer dragTimer; 
    private readonly int interval = 3000; 

    public DragDropTimer() 
    { 
     dragTimer = new System.Timers.Timer(); 
     dragTimer.Interval = interval; 
     dragTimer.Elapsed += new ElapsedEventHandler(DragDropTimerElapsed); 
     dragTimer.Enabled = false; 
     dragTimer.AutoReset = false; 
    } 

    void DragDropTimerElapsed(object sender, ElapsedEventArgs e) 
    { 
     Initiate(); 
    } 

    public void Initiate() 
    { 
     // Stops UI from freezing, call action async. 
     DoDragDropDelegate doDragDrop = new DoDragDropDelegate(DragDropAction); 

     // No async callback or object required 
     doDragDrop.BeginInvoke(null, null); 
    } 

    private void DragDropAction() 
    { 
     dragTimer.Enabled = false; 

     // Do your work here. or do work before and disable your timer upto you. 

    } 

} 

Итак, мы имеем базовый класс DragDropTimer. Мы устанавливаем интервал, который мы хотим на конструкторе, вы можете изменить это, если хотите, и мы вызываем DragDropTimerElapsed по истекшему таймеру.

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

0

Другие варианты, чтобы выполнить падение в отдельном потоке следующим образом

Task.Factory.StartNew(() => { ... }); 
Смежные вопросы