2017-10-23 1 views
0

내 기본 클래스에서 wpf 창 (p) 및 레이블 (내용)에 주어진 메시지와 함께 창을 표시하는 함수를 만듭니다. 이 완벽하게 잘 작동WPF 창 별도 스레드에서 특정 기능을 업데이트하지 않습니다

namespace Wilson.Utils 
{ 
    class Commands 
    { 
     public void start() 
     { 
      ///creates notification window thats reads "hello world" 
      MainWindow.NotifProc("hello world"); 

      ///creates notification window thats reads "test1" 
      ///For some reason reads "hello world" 
      MainWindow.NotifProc("test1"); 

      ///creates notification window thats reads "test2" 
      ///For some reason reads "hello world" 
      MainWindow.NotifProc("test2");    
     } 

     ///creates global string 
     public static class MyGlobals 
     { 
      public static string inputtext = ""; 
     } 
    } 
} 

나는 그런 것처럼 전화를 다른 네임 스페이스에있는 다른 클래스 다음

public partial class MainWindow : Window 
{ 
    ///Creates Window 
    public static Wils0n.Window1 p = new Wils0n.Window1(); 

    /// <summary> 
    /// creates notif bar with message 
    /// </summary> 
    /// <param name="message">Message for notif bar</param> 
    public static void NotifProc(string message) 
    { 
     ///sets global string to message 
     Commands.MyGlobals.inputtext = message; 

     p.Dispatcher.Invoke(new Action(delegate() 
     { 
     MainWindow.p.Topmost = true; 
     MainWindow.p.Top = 0; 

     ///sets label content to global string (this only works once) 
     MainWindow.p.content.Content = Commands.MyGlobals.inputtext; 

     MainWindow.p.Left = System.Windows.SystemParameters.WorkArea.Width/2 - (MainWindow.p.Width/2); 
     MainWindow.p.Show(); 
     Thread.Sleep(2000); 
     while (MainWindow.p.Top != -114) 
     { 
      MainWindow.p.Top -= 3; 
      Thread.Sleep(15); 
     } 
     MainWindow.p.Hide(); 
     } 
     )); 
    } 
} 

.. 처음에만, 나는 다른 메시지와 함께 다시 호출 경우 메시지를 업데이트하지는 않으나 notif는 여전히 작동하여 그냥 이전 메시지를 표시합니다.

나는 또한 내가 "다른 스레드가 그것을 소유하고 있기 때문에 개체에 액세스 할 수 없습니다"읽기 오류가 Dispatcher.Invoke없이 MainWindow.p.OpacityMainWindow.p.Background

을 변경하여이 문제가 있었다.

Commands.MyGlobals.inputtext = message;을 제거하고 Commans.MyGlobals.inputtext = "test1"MainWindow.NotifProc("test1"); 앞에 붙이면 여전히 작동하지 않습니다. 나는 또한 같은 클래스를 만드는 시도

는 :

public static class ExtensionMethods 
{ 
    private static Action EmptyDelegate = delegate() { }; 

    public static void Refresh(this UIElement uiElement) 
    { 
     uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); 
    } 
} 

및 추가 :

p.content.Refresh(); 

하지만 운이 없었다. 도움이 될 것입니다. :/

편집

아마 최고의 아니지만 내가 수정을 찾기 위해 관리 : 대신 시작 부분에 새 창을 만드는 나는 새로운 윈도우 창 애니메이션이 호출 될 때마다 만들 수 있습니다. VS는 STA 스레드이어야하고 STA 스레드에서 호출해야하므로 마지막으로 창 애니메이션의 끝 부분에 검사를 추가하여 첫 번째 작업이 완료 될 때까지 새 창을 만들 수 없도록합니다.

나의 새로운 NotifProc 기능은 다음과 같습니다 :

public static void NotifProc(string message) 
    { 
     Tools.MyGlobals.notifmessage = message; 
     var thread = new Thread(new ThreadStart(STAThread)); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 
     thread.Join(); 
    } 
    private static void STAThread() 
    { 
     Wils0n.Window1 p = new Wils0n.Window1(); 
     p.content.Content = Tools.MyGlobals.notifmessage; 
     p.content.Refresh(); 
     p.Topmost = true; 
     p.Top = 0; 
     p.Left = System.Windows.SystemParameters.WorkArea.Width/2 - (p.Width/2); 
     p.Show(); 

     Thread.Sleep(2000); 
     while (p.Top != -114) 
     { 
      p.Top -= 3; 
      Thread.Sleep(15); 
     } 
     p.Close(); 
    } 
+0

가능한 중복 https://stackoverflow.com/questions/661561/how-do-i-update-the-gui -from-another-thread-in-c) – MickyD

+0

사람들은 항상 스레드를 한 번에 몇 초 동안 만 잠자기 상태로 만들 것을 항상 주장합니까? – MickyD

+1

UI 스레드보다 여기에 관련된 다른 스레드가없는 것으로 보입니다. 'Dispatcher.Invoke'를 호출하면 새 스레드가 생성되지 않고 UI 스레드에서 대리자가 실행됩니다. 그러나 UI 스레드는 Thread.Sleep을 호출하여 차단됩니다. 대신'await Task.Delay (...)'를 사용하십시오. – Clemens

답변

0

를 대신 차단 따라서 UI 스레드에서 Thread.Sleep를 호출, 그리고, 당신은 단순히이 같은 창 위치 애니메이션을해야합니다

public static void NotifProc(string message) 
{ 
    p.Content.Content = message; 
    p.Left = SystemParameters.WorkArea.Width/2 - (p.Width/2); 
    p.Top = 0; 
    p.Topmost = true; 
    p.Show(); 

    var animation = new DoubleAnimation 
    { 
     To = -114, 
     BeginTime = TimeSpan.FromSeconds(2), 
     Duration = TimeSpan.FromSeconds(0.57) 
    }; 

    animation.Completed += (s, e) => p.Hide(); 

    p.BeginAnimation(TopProperty, animation); 
} 

을 UI 스레드가 아닌 다른 스레드에서 메서드를 호출하려면 다음과 같이하십시오.

Application.Current.Dispatcher.Invoke(() => NotifProc(...)); 

또는

MainWindow.p.Dispatcher.Invoke(() => NotifProc(...)); 
[나는 C#에서 다른 스레드에서 GUI를 업데이트하려면 어떻게?]의 (
+0

나는 이것을 시도했지만 여전히 다른 스레드가 그것을 소유하고 있기 때문에 "개체에 액세스 할 수 없습니다." 감사합니다. btw를 돕는 것에 대해 감사합니다. – MrMister

+0

답변에 표시된대로'Application.Current.Dispatcher.Invoke'를 시도 했습니까? 아마도 질문을 편집하고 수행하려는 것을 보여 주어야합니다. – Clemens

+0

'Application.Current.Dispatcher.Invoke'를 시도해 보았습니다. 찾지 못해서 MainWindow.p를 찾았지만 찾았지만 "액세스 할 수 없습니다 ..". 내가 일주일 전만 프로그래밍을 시작했다고 설명하는 것이 최선이 아닌 것은 유감스럽게 생각합니다. 원래 스레드는 음성 인식기를 시작한 다음 입력을 다른 네임 스페이스에있는 일반 클래스의 공용 void로 보냅니다. 창 등을 움직일 수는 있지만 색상, 텍스트 또는 불투명도를 두 번 이상 변경할 수 없습니다. – MrMister

관련 문제