Ich habe den folgenden Beispielcode, der jedes Mal zoomt, wenn eine Taste gedrückt wird:
XAML:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="myCanvas">
<Canvas.LayoutTransform>
<ScaleTransform x:Name="myScaleTransform" />
</Canvas.LayoutTransform>
<Button Content="Button"
Name="myButton"
Canvas.Left="50"
Canvas.Top="50"
Click="myButton_Click" />
</Canvas>
</Window>
* .cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
myScaleTransform.ScaleX =
myScaleTransform.ScaleY =
myScaleTransform.ScaleX + 1;
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
}
private Point GetMyByttonLocation()
{
return new Point(
Canvas.GetLeft(myButton),
Canvas.GetTop(myButton));
}
}
Die Ausgabe ist:
scale 1, location: 296;315
scale 2, location: 296;315
scale 2, location: 346;365
scale 3, location: 346;365
scale 3, location: 396;415
scale 4, location: 396;415
Wie Sie sehen können, gibt es ein Problem, das ich mithilfe von lösen wollte, Application.DoEvents();
aber ... es existiert nicht a priori in .NET 4.
Was ist zu tun?
Antworten:
Die alte Application.DoEvents () -Methode wurde in WPF zugunsten der Verwendung eines Dispatchers oder eines Background Worker-Threads für die von Ihnen beschriebene Verarbeitung veraltet . Unter den Links finden Sie einige Artikel zur Verwendung beider Objekte.
Wenn Sie Application.DoEvents () unbedingt verwenden müssen, können Sie einfach die Datei system.windows.forms.dll in Ihre Anwendung importieren und die Methode aufrufen. Dies wird jedoch wirklich nicht empfohlen, da Sie alle Vorteile verlieren, die WPF bietet.
quelle
Application.DoEvents
nach dem Inkrementieren von myScaleTransform.ScaleX aufrufen. Ich weiß nicht, ob dies mit Dispatcher möglich ist.Versuchen Sie so etwas
quelle
public static void DoEvents(this Application a)
Application.Current
manchmal null ist ... also ist es vielleicht nicht ganz gleichwertig.Nun, ich habe gerade einen Fall getroffen, in dem ich mit der Arbeit an einer Methode beginne, die auf dem Dispatcher-Thread ausgeführt wird, und die blockiert werden muss, ohne den UI-Thread zu blockieren. Es stellt sich heraus, dass msdn erklärt, wie ein DoEvents () basierend auf dem Dispatcher selbst implementiert wird:
(entnommen aus der Dispatcher.PushFrame-Methode )
Einige bevorzugen es möglicherweise in einer einzigen Methode, die dieselbe Logik erzwingt:
quelle
Wenn Sie nur die Fenstergrafik aktualisieren müssen, verwenden Sie diese besser
quelle
scheint auch zu funktionieren.
quelle
Ein Problem bei beiden vorgeschlagenen Ansätzen besteht darin, dass die CPU im Leerlauf ausgelastet ist (meiner Erfahrung nach bis zu 12%). Dies ist in einigen Fällen nicht optimal, beispielsweise wenn das Verhalten der modalen Benutzeroberfläche mithilfe dieser Technik implementiert wird.
Die folgende Variante führt eine minimale Verzögerung zwischen Frames mit einem Timer ein (beachten Sie, dass sie hier mit Rx geschrieben wird, aber mit jedem regulären Timer erreicht werden kann):
quelle
Seit der Einführung von
async
und es istawait
nun möglich, den UI-Thread teilweise durch einen (ehemals) * synchronen Codeblock abzugeben, indemTask.Delay
zIch bin ehrlich, ich habe es nicht mit dem genauen Code oben versucht, aber ich verwende es in engen Schleifen, wenn ich viele Artikel in eine
ItemsControl
Vorlage mit einer teuren Artikelvorlage lege und manchmal eine kleine Verzögerung hinzufüge, um den anderen zu geben Sachen auf der Benutzeroberfläche mehr Zeit.Beispielsweise:
Wenn es im Windows Store einen schönen Themenübergang in der Sammlung gibt, ist der Effekt durchaus wünschenswert.
Luke
quelle
await
veranlasst der Compiler, den Rest der asynchronen Methode als Fortsetzung der erwarteten Aufgabe anzumelden . Diese Fortsetzung erfolgt im UI-Thread (gleicher Synchronisierungskontext). Die Steuerung kehrt dann zum Aufrufer der asynchronen Methode zurück, dh zum WPF-Ereignissubsystem, in dem Ereignisse ausgeführt werden, bis die geplante Fortsetzung einige Zeit nach Ablauf der Verzögerungszeit ausgeführt wird.Machen Sie Ihr DoEvent () in WPF:
Arbeite gut für mich!
quelle
Beantwortung der ursprünglichen Frage: Wo ist DoEvents?
Ich denke, DoEvents ist VBA. Und VBA scheint keine Schlaffunktion zu haben. VBA bietet jedoch die Möglichkeit, genau den gleichen Effekt wie Sleep oder Delay zu erzielen. Mir scheint, dass DoEvents dem Schlaf (0) entspricht.
In VB und C # handelt es sich um .NET. Und die ursprüngliche Frage ist eine C # -Frage. In C # würden Sie Thread.Sleep (0) verwenden, wobei 0 0 Millisekunden ist.
Du brauchst
oben in der Datei, um zu verwenden
in Ihrem Code.
quelle