2016-02-02 16 views
6

La mia applicazione ha una funzione semplice in cui si collega a Excel e eseguirà operazioni di trascinamento della selezione tra di loro. In particolare, sto solo prendendo alcuni valori di testo dalla mia applicazione, trascinandoli in Excel e rilasciandoli.DragDrop.DoDragDrop non restituisce quando esegue un'operazione di rilascio in Excel

Questo funziona il 90% del tempo, ma stranamente in determinati momenti, la mia applicazione si blocca solo. Allego il debugger e metto in pausa l'esecuzione e rimane bloccato a DragDrop.DoDragDrop - questa funzione non ritorna mai e la mia applicazione si bloccherà per sempre.

C'è un modo per garantire che lo DoDragDrop possa restituire? O una specie di timeout? Ciò accade solo a volte quando rilasciamo i dati in Excel, quindi per quello che so, il drop è in fase di completamento e la funzione dovrebbe tornare all'interno della mia applicazione.

Ecco il codice che uso:

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

GetDragDropString() è solo una funzione che restituisce la stringa di dati da cadere in Excel. sender è solo il componente dell'interfaccia utente che sto trascinando. Come una griglia, o casella di modifica, casella di testo, ecc. Potrebbe essere uno di quelli.

Grazie per qualsiasi aiuto!

MODIFICA: poiché c'è un problema con DragDrop.DoDragDrop di ritorno in alcuni casi, forse qualcuno può aiutare con la scrittura di un timeout adeguato? Ho provato ad avviare un nuovo Thread e averlo scaduto, che funziona in casi semplici e quando il lavoro all'interno del thread non richiede risorse dell'interfaccia utente. Tuttavia, quando chiamo DoDragDrop in un nuovo thread con un timeout, verrà generata un'eccezione che dice che il thread non può accedere all'oggetto perché lo possiede un thread diverso. Quindi ho bisogno di chiamare questa funzione all'interno della stessa discussione. Quindi in sostanza ho bisogno di un timeout sul thread dell'interfaccia utente quando questa funzione non riesce a tornare in un certo periodo di tempo.

+0

@HansPassant grazie per la risposta - Il trascinamento avviene sempre dall'utente. Stai dicendo che devo gestire i callback di Excel nel mio codice applicazione? Come le chiamate di DragEnter/Over/Drop che hai citato? Ho solo pensato che se l'utente trascina i dati in Excel da sé, che la funzione DoDragDrop ritornerà in seguito. Funziona il 90% delle volte, ma a volte si congela. – ryrich

risposta

1

Penso che la seguente dovrebbe fare il lavoro ma mi scomposizione come vado avanti

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. 

    } 

} 

Così abbiamo una classe base DragDropTimer. Impostiamo l'intervallo che vogliamo sul costruttore, potremmo volerlo cambiare se lo desideri e chiamiamo il timer DragDropTimerElapsed.

Initiate è la funzione necessaria per avviare il trascinamento, crea un delegato semplice e chiediamo di eseguire i passaggi DragAction, questo è dove si fa tutto il lavoro e il timer viene disabilitato. Puoi scegliere di disabilitare il timer solo se hai successo con DragDrop. Se il timer scade, chiamiamo nuovamente Initiate per ricominciare tutto da capo.

0

Un'altra possibilità è di eseguire goccia in un thread separato nel modo seguente

Task.Factory.StartNew(() => { ... });