2016-02-02 3 views
6

Meine Anwendung verfügt über eine einfache Funktion, wo es an Excel hängt und Drag-Drop-Operationen zwischen ihnen durchführen wird. Insbesondere nehme ich nur einige Textwerte aus meiner Anwendung, ziehe sie in Excel und lasse sie fallen.DragDrop.DoDragDrop wird nicht zurückgegeben, wenn Sie eine Operation in Excel ausführen

Dies funktioniert 90% der Zeit, aber seltsamerweise zu bestimmten Zeiten, friert meine Anwendung gerade ein. Ich füge den Debugger an und pausiere die Ausführung und es bleibt bei DragDrop.DoDragDrop hängen - diese Funktion kehrt nie zurück und meine Anwendung wird für immer hängen.

Gibt es eine Möglichkeit sicherzustellen, dass DoDragDrop zurückgeben kann? Oder eine Art Timeout? Dies passiert nur manchmal, wenn ich die Daten in Excel ablege, also wird das Löschen nach meinem Wissen beendet und die Funktion sollte innerhalb meiner Anwendung zurückkehren.

Hier ist der Code, den ich verwenden:

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

GetDragDropString() ist nur eine Funktion, die die Zeichenfolge von Daten fallen in Excel zurückgibt. sender ist nur die UI-Komponente, die ich ziehe. Wie ein Gitter, oder ein Eingabefeld, ein Textfeld, usw. Kann eines davon sein.

Danke für jede Hilfe!

EDIT: Da gibt es ein Problem mit DragDrop.DoDragDrop Rückkehr in bestimmten Fällen, vielleicht kann jemand helfen mit einem richtigen Timeout schreiben? Ich habe versucht, ein neues Thread zu starten und es Zeitüberschreitung zu haben, die in einfachen Fällen funktioniert und wenn die Arbeit innerhalb des Threads UI-Ressourcen nicht benötigt. Wenn ich jedoch DoDragDrop in einem neuen Thread mit einer Zeitüberschreitung aufruft, wird eine Ausnahme ausgelöst, die besagt, dass der Thread nicht auf das Objekt zugreifen kann, da ein anderer Thread es besitzt. Also muss ich diese Funktion im selben Thread aufrufen. Also im Wesentlichen brauche ich eine Zeitüberschreitung auf dem UIhread, wenn diese Funktion nicht in einer bestimmten Zeit zurückkehrt.

+0

@HansPassant dank ausführen - Der Widerstand wird immer durch den Benutzer. Willst du sagen, dass ich Excel Callbacks in meinem Anwendungscode behandeln muss? Wie die DragEnter/Over/Drop Anrufe, die Sie erwähnt haben? Ich nahm nur an, wenn der Benutzer die Daten selbst in Excel zieht, dass die DoDragDrop Funktion danach zurückkehrt. Dies funktioniert 90% der Zeit, aber manchmal friert es stattdessen ein. – ryrich

Antwort

1

denke ich Folgendes sollte die Arbeit tun, aber ich werde es brechen, wie ich entlang

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. 

    } 

} 

gehen So haben wir eine Basisklasse DragDropTimer. Wir setzen das Intervall, das wir für den Konstruktor haben wollen, vielleicht möchten Sie das ändern, wenn Sie möchten, und wir rufen den DragDropTimerElapsed on timer verstrichen auf.

Initiate ist die Funktion, die Sie benötigen, um das Ziehen zu starten, es erstellt einen einfachen Delegaten und wir bitten es, die DragAction Schritte auszuführen, das ist, wo Sie alle Ihre Arbeit tun und der Timer deaktiviert wird. Sie können den Timer nur deaktivieren, wenn DragDrop erfolgreich ist. Wenn der Timer abgelaufen ist, rufen wir erneut Initiate auf, um erneut von vorne zu beginnen.

0

Weiteren Optionen sind Abfall in einem separaten Thread in der folgenden Art und Weise für die Antwort

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