İlk başta gördüğümüz bir olay bulan köpürme olabileceğini düşündüm, bu yüzden olarakdökülmüş bir değişken, ikinci çağrının düğmeden gelip gelmediğini göstermek için işleyici lambdaya eklenmiştir. @Simon Mourier, sonuç: evet değerler aynıdır) ve onun kurucu etiketinden veya görsel ağacın yukarı ya da aşağıdan başka bir şeyden değil.
Bundan sonra karar verildiğinde, iki geri bildirimin çağrı yığınlarına daha yakından bakıldığında, iş parçacığıyla ilgili hipotezi destekleyen bir şey ortaya çıkar. UIAComWrapper'ı kaynaktan derledim, kaynaktan derledim ve kaynak sunucu sembolleri ile debug edilmiş ve yerel olarak.
bu ilk geri arama çağrı yığını: Bu çıkış noktası mesajı pompa gösterir,
. Çekirdek WndProc, neredeyse tüm Windows sürümlerinin bir özetinde, neredeyse bir sol fare olarak kod çözme, düğme sınıfının OnClick()
işleyicide sona ermesine kadar, inanılmaz derecede kalın bir çerçeve nesnesi tabakası ile bu kabarcıklar arasında abone otomasyon olayı yükseltildi ve lamdamıza yönlendirildi. Şimdiye kadar beklenmedik bir şey yok.
ve bu ikinci geri arama çağrı yığını:
Bu ikinci geri UIAutomationCore
bir yapay olduğunu ortaya koymaktadır. Ve: kullanıcı iş parçacığı üzerinde değil, kullanıcı iş parçacığı üzerinde çalışır. Bu nedenle, abone olan her parçanın bir kopyasını almasını ve UI iş parçacığının her zaman olmasını sağlayan bir mekanizma vardır.
Ne yazık ki, lambda'da ortaya çıkan tüm argümanlar birinci ve ikinci aramalar için aynıdır. Çağrı yığınlarını karşılaştırmak mümkün olsa da, zamanlama/sayma olaylarından bile daha kötü bir çözüm olacaktır.
Ama: Sen ipliğine olayları filtrelemek ve bunlardan yalnızca bir tüketebilir: çıktı penceresinde
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Interop;
using System.Threading;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs routedEventArgs)
{
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
Task.Run(() =>
{
var element = AutomationElement.FromHandle(windowHandle);
Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent, element, TreeScope.Descendants,
(s, a) =>
{
var ele = s as AutomationElement;
var invokingthread = Thread.CurrentThread;
Debug.WriteLine($"Invoked on {invokingthread.ManagedThreadId} for {ele}, event # {a.EventId.Id}");
/* detect if this is the UI thread or not,
* reference: http://stackoverflow.com/a/14280425/1132334 */
if (System.Windows.Threading.Dispatcher.FromThread(invokingthread) == null)
{
Debug.WriteLine("2nd: this is the event we would be waiting for");
}
else
{
Debug.WriteLine("1st: this is the event raised on the UI thread");
}
});
});
}
private void button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Clicked!");
}
}
}
Sonucu:
Invoked on 1 for System.Windows.Automation.AutomationElement, event # 20009
1st: this is the event raised on the UI thread
Invoked on 9 for System.Windows.Automation.AutomationElement, event # 20009
2nd: this is the event we would be waiting for
Sorunu üretebilir. Ancak, başka bir süreçten üretemiyorum (sadece bir olay ortaya çıktı). Bir hata olabilir, ancak UIA işlem dışı müşteriler için tasarlandı, bunu neden aynı işlemden yapmak istersiniz? –
VSTO ile kullanım için. Excel API, tüm buton tıklamalarına erişim sağlamaz. Otomasyon bunları tespit etmek için iyi çalışır, ancak iki kez gelirler. – jan
Tamam. Pekala, bulabildiğim tek kötü çözüm 1) zaman olaylarıdır, 2) kaynağın aynı nesne olup olmadığını belirleme (olay kaynağının GetHashCode'unu karşılaştıran - bir OtomasyonElementi - burada mantıklı görünüyor) 3) Eğer iki olay gerçekleşirse x milisaniye sonra ikiye katlandığını beyan ederiz. –