어플리케이션은 어디에 있습니까?WPF의 DoEvents()?
버튼을 누를 때마다 확대/축소되는 다음 샘플 코드가 있습니다.
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));
}
}
출력은 다음과 같습니다.
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
보다시피, 문제가 있는데, 나는 그것을 이용해서 해결한다고 생각했다.Application.DoEvents();
하지만... 에는 선험자가 존재하지 않습니다.넷 4
무엇을 해야 하나?
이런 거 해봐
public static void DoEvents()
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background,
new Action(delegate { }));
}
방금 Dispatcher 스레드에서 실행되는 메서드로 작업을 시작한 경우 UI 스레드를 차단하지 않고 차단해야 합니다.msdn은 디스패처 자체를 기반으로 DoEvents()를 구현하는 방법을 설명합니다.
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
(디스패처로부터 취득).Push Frame 메서드)
일부에서는 동일한 논리를 적용하는 단일 방식을 선호할 수 있습니다.
public static void DoEvents()
{
var frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(
delegate (object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}),frame);
Dispatcher.PushFrame(frame);
}
참고 항목: https://kent-boogaart.com/blog/dispatcher-frames
오래된 어플리케이션DoEvents() 메서드는 WPF에서 Dispatcher 또는 Background Worker Thread를 사용하여 설명한 대로 처리를 수행하는 것을 권장하지 않습니다.두 개체를 모두 사용하는 방법에 대한 몇 가지 기사는 링크를 참조하십시오.
꼭 어플리케이션을 사용해야 하는 경우.DoEvents()를 선택하면 시스템을 Import할 수 있습니다.창문들.forms.displays를 어플리케이션에 삽입하여 메서드를 호출합니다.단, WPF가 제공하는 이점을 모두 잃게 되므로 이 방법은 권장하지 않습니다.
윈도우 그래픽을 업데이트해야 할 경우 다음과 같이 사용하는 것이 좋습니다.
public static void DoEvents()
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Render,
new Action(delegate { }));
}
myCanvas.UpdateLayout();
효과가 있는 것 같습니다.
두 가지 접근방식의 문제 중 하나는 CPU 사용률이 유휴 상태(내 경험으로는 최대 12%)라는 것입니다.예를 들어 이 기술을 사용하여 모달 UI 동작을 구현하는 경우 등 경우에 따라서는 이 방법이 최적이 아닙니다.
다음 변형에서는 타이머를 사용하는 프레임 간에 최소 지연이 발생합니다(여기서는 Rx로 기술되어 있지만 일반 타이머로 실행할 수 있습니다).
var minFrameDelay = Observable.Interval(TimeSpan.FromMilliseconds(50)).Take(1).Replay();
minFrameDelay.Connect();
// synchronously add a low-priority no-op to the Dispatcher's queue
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => minFrameDelay.Wait()));
「 」의 async
★★★★★★★★★★★★★★★★★」await
이전 동기 을 경유하여 할 수 .이러한 블록은 UI를 사용하여 ()* 블록입니다.Task.Delay
private async 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;
await Task.Delay(1); // In my experiments, 0 doesn't work. Also, I have noticed
// that I need to add as much as 100ms to allow the visual tree
// to complete its arrange cycle and for properties to get their
// final values (as opposed to NaN for widths etc.)
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
}
솔직히 말씀드리면, 저는 위의 정확한 코드를 사용해 본 적이 없지만, 많은 아이템을 넣을 때 엄격한 루프로 사용합니다.ItemsControl
비싼 아이템 템플릿이 있어 UI 상의 다른 아이템에 시간을 더 주기 위해 약간의 지연을 추가할 수 있습니다.
예를 들어 다음과 같습니다.
var levelOptions = new ObservableCollection<GameLevelChoiceItem>();
this.ViewModel[LevelOptionsViewModelKey] = levelOptions;
var syllabus = await this.LevelRepository.GetSyllabusAsync();
foreach (var level in syllabus.Levels)
{
foreach (var subLevel in level.SubLevels)
{
var abilities = new List<GamePlayingAbility>(100);
foreach (var g in subLevel.Games)
{
var gwa = await this.MetricsRepository.GetGamePlayingAbilityAsync(g.Value);
abilities.Add(gwa);
}
double PlayingScore = AssessmentMetricsProcessor.ComputePlayingLevelAbility(abilities);
levelOptions.Add(new GameLevelChoiceItem()
{
LevelAbilityMetric = PlayingScore,
AbilityCaption = PlayingScore.ToString(),
LevelCaption = subLevel.Name,
LevelDescriptor = level.Ordinal + "." + subLevel.Ordinal,
LevelLevels = subLevel.Games.Select(g => g.Value),
});
await Task.Delay(100);
}
}
Windows Store 에서는, 컬렉션에 좋은 테마 전환이 있는 경우, 그 효과는 매우 바람직합니다.
루크
- 댓글을 봐주세요.답변을 빠르게 쓸 때 동기화된 코드 블록을 가져다가 스레드를 다시 발신자에게 넘겨주는 동작을 생각하고 있었습니다.그 결과, 코드 블록은 비동기화 되었습니다.나는 내 대답을 완전히 바꾸고 싶지 않다. 왜냐하면 독자들은 서비와 내가 무슨 말다툼을 하고 있었는지 볼 수 없기 때문이다.
WPF에서 DoEvent()를 만듭니다.
Thread t = new Thread(() => {
// do some thing in thread
for (var i = 0; i < 500; i++)
{
Thread.Sleep(10); // in thread
// call owner thread
this.Dispatcher.Invoke(() => {
MediaItem uc = new MediaItem();
wpnList.Children.Add(uc);
});
}
});
t.TrySetApartmentState(ApartmentState.STA); //for using Clipboard in Threading
t.Start();
잘 해 주세요!
푸시 프레임:
using System.Windows.Threading;
...
var frame = new DispatcherFrame();
Dispatcher.PushFrame(frame);
종료 프레임:
frame.Continue = false;
다음으로 Dispatcher Frame을 사용하여 Windows Forms DoEvents 메서드와 유사한 결과를 얻는 예를 나타냅니다.
https://learn.microsoft.com/dotnet/api/system.windows.threading.dispatcher.pushframe
갱신일 :
재미있는 제작 방법Task.Delay()
비고정적인
// How to use: Task.Delay(250).WaitNB();
public static void WaitNB(this Task task)
{
var frame = new DispatcherFrame();
task.ContinueWith(t => frame.Continue = false);
Dispatcher.PushFrame(frame);
}
원래 질문에 대한 답변:DoEvents는 어디에 있나요?
나는 DoEvents가 VBA라고 생각해.그리고 VBA에는 Sleep 기능이 없는 것 같습니다.그러나 VBA는 Sleep 또는 Delay와 정확히 동일한 효과를 얻을 수 있는 방법이 있습니다.DoEvents는 Sleep(0)과 동등한 것 같습니다.
VB 및 C#에서는 거래처입니다.NET. 그리고 첫 번째 질문은 C# 질문입니다.C#에서는 스레드를 사용합니다.sleep(0). 여기서 0은 0밀리초입니다.
당신은 필요하다
using System.Threading.Task;
사용하기 위해 파일 맨 위에 있는
Sleep(100);
당신의 코드로.
언급URL : https://stackoverflow.com/questions/4502037/where-is-the-application-doevents-in-wpf
'programing' 카테고리의 다른 글
IEnumberable vs List - 사용방법그들은 어떻게 일하는가? (0) | 2023.04.10 |
---|---|
Apple 프로덕션 푸시 SSL 인증서를 .p12 형식으로 내보낼 수 없습니다. (0) | 2023.04.10 |
스와이프를 추가하여 UITable View Cell 삭제 (0) | 2023.04.10 |
삽입과 삽입 (0) | 2023.04.10 |
2D Excel 테이블을 1D로 "축소"하거나 "축소"하는 방법은 무엇입니까? (0) | 2023.04.10 |