2012-08-24 2 views
0

Я пытаюсь связать существующий API C# WPF с приложением Java.Проблемы с потоками при использовании библиотеки WPF в Java-приложении?

До сих пор я успешно использовал jni4net для создания прокси-интерфейсов между Java и .NET-кодом.

Эта интеграция производства вопросы поточной STA с отображаемым WPF UI-х:

System.InvalidOperationException: The calling thread must be STA, because many UI components require this. 
    at System.Windows.Input.InputManager..ctor() 
    at System.Windows.Input.InputManager.GetCurrentInputManagerImpl() 
    at System.Windows.Input.KeyboardNavigation..ctor() 
    at System.Windows.FrameworkElement.FrameworkServices..ctor() 
    at System.Windows.FrameworkElement.EnsureFrameworkServices() 
    at System.Windows.FrameworkElement..ctor() 
    at System.Windows.Controls.Control..ctor() 
    at System.Windows.Window..ctor() 

Это было преодолено с помощью следующего шаблона для загрузки в WPF UI, используя ShowDialog:

Thread thread = new Thread(new ParameterizedThreadStart(ParameterizedMethodName)); 
thread.SetApartmentState(ApartmentState.STA); 
thread.Start(parameter); 
thread.Join(); 

Теперь, однако, Я испытываю исключения, похожие на следующие при использовании пользовательского интерфейса WPF, щелчок мышью или нажатие клавиши может вызвать следующее (этот пример был нажатием мыши):

System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it. 
    at System.Windows.Threading.Dispatcher.VerifyAccess() 
    at System.Windows.DependencyObject.GetValue(DependencyProperty dp) 
    at System.Windows.Input.InputBinding.get_Command() 
    at System.Windows.Input.InputBindingCollection.FindMatch(Object targetElement, InputEventArgs inputEventArgs) 
    at System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs) 
    at System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e) 
    at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) 
    at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target) 
    at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs) 
    at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised) 
    at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args) 
    at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args) 
    at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted) 
    at System.Windows.Input.InputManager.ProcessStagingArea() 
    at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input) 
    at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport) 
    at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel) 
    at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) 
    at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) 
    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 
    at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) 
    at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) 
    at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) 
    at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) 
    at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) 
    at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) 
    at System.Windows.Window.ShowHelper(Object booleanBox) 
    at System.Windows.Window.Show() 
    at System.Windows.Window.ShowDialog() 

В настоящее время я не уверен, как решить эту проблему и определить причину проблемы из трассировки стека.

Любая помощь/совет очень ценится.

ответ

0

Я не могу предложить много советов относительно решения, но я могу рассказать вам о проблеме. Весь ваш код WPF должен работать в той же теме (предположительно той, которую вы создаете). Ошибка, которую вы получаете, заключается в том, что что-то пыталось получить доступ к элементу управления WPF из другого потока.

Итак, скажем, у вас есть вызов API, который показывает диалог, а ваш код java вызывает MyApi.ShowDialog. Ваш метод API ShowDialog не может просто вызвать MyDialog.ShowDialog(), потому что этот вызов компонента пользовательского интерфейса будет поступать из потока java. Вместо этого ваш API должен быть достаточно умным, чтобы перенаправить эти вызовы в соответствующий поток WPF (UI).

Так он должен сделать что-то вроде:

if(!CheckAccess()) 
    MyDialog.Dispatcher.BeginInvoke(DeleageToShowDialog); 

К сожалению, это, вероятно, означает, что вы будете иметь, чтобы сделать много работы на вашем API, потому что он, вероятно, не учитывает проблем многопоточности, как это ,

+0

Спасибо. Я уже знаю об использовании CheckAccess() и уже написал для этого метод расширения. Проблема только в том, что я не знаю, с чего начать тестирование! Трассировка стека из исключения не указывает меня в сторону проблемы, так как это трассировка стека .NET ... – Paul

+0

Я не думаю, что это действительно имеет значение, найдите место в вашем WPF API, который вызывает 'ShowDialog() 'и убедитесь, что он потокобезопасен. Вам нужно будет это сделать или вы в конечном итоге устраните эту конкретную ошибку, а затем перейдете в другую, а другую, а другую. – CodingGorilla

+0

Я по-прежнему испытываю такое же исключение в своем основном WPF-интерфейсе, даже если ShowDialog() завернут CheckAccess() и BeginInvoke(). – Paul

 Смежные вопросы

  • Нет связанных вопросов^_^