質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

2回答

7265閲覧

WPFでawait Task.RunにしたらSTAエラーになっています

cancat

総合スコア313

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

2クリップ

投稿2017/06/14 02:44

こんにちは。
Windows10でWPFのアプリケーションを開発しています。
Visual Studio 2015 Communityを使っています。

###前提・実現したいこと
重たい処理の時にProgressBarを表示したいです。

###試したこと
xamlでprogressbarを配置し、ボタンの処理にvisible/hidden処理を追加、重たい処理をawait Task.Runで囲みました。

await Task.Run(() =>
{
});
を外せば問題なく動作します。

public static Window CreateView<T>(T viewModel) public static bool? ShowModalWindow<T>(T viewModel) private async void outputExamResultAsync()

をすべて [STAThread]
にしても、同じエラーです。

###発生している問題・エラーメッセージ
型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が mscorlib.dll で発生しました
{"呼び出しスレッドは、多数の UI コンポーネントが必要としているため、STA である必要があります。"}

###該当のソースコード

xaml

1 <Border Width="300" Height="100" HorizontalAlignment="Center" VerticalAlignment="Center" Background="LightGray" Visibility="{Binding IndicatorVisibility}"> 2 <Grid> 3 <ProgressBar IsIndeterminate="True"/> 4 </Grid> 5 </Border>

C#

1 private Visibility indicatorVisibility = Visibility.Hidden; 2 public Visibility IndicatorVisibility 3 { 4 get { return indicatorVisibility; } 5 set 6 { 7 indicatorVisibility = value; 8 RaisePropertyChanged("IndicatorVisibility"); 9 } 10 }

C#

1 private async void outputExamResultAsync() 2 { 3 IndicatorVisibility = Visibility.Visible; 4 5 await Task.Run(() => 6 { 7 ResultWindowViewModel resultWindowViewModel = new ResultWindowViewModel(); 8 resultWindowViewModel.重たい処理(); 9 LocatorClass.ShowModalWindow(resultWindowViewModel); 10 }); 11 12 IndicatorVisibility = Visibility.Hidden; 13 }

C#

1LocatorClass 2 public static bool? ShowModalWindow<T>(T viewModel) 3 { 4 var window = CreateView(viewModel); 5 if (window == null) 6 { 7 return null; 8 } 9 10 Application.Current.MainWindow.IsEnabled = false; 11 12 window.Owner = Application.Current.MainWindow; 13 window.WindowStartupLocation = WindowStartupLocation.CenterOwner; 14 var result = window.ShowDialog(); 15 16 Application.Current.MainWindow.IsEnabled = true; 17 return result; 18 } 19 20 public static Window CreateView<T>(T viewModel) 21 { 22 // View を生成し、DataContext に ViewModel を設定する 23 Type viewType = ViewModels[viewModel.GetType()]; 24 Window window = Activator.CreateInstance(viewType) as Window; //<=この行でエラー。 25 return window; 26 } 27 28 29

###補足情報(言語/FW/ツール等のバージョンなど)
Microsoft Visual Studio Community 2015
Version 14.0.25424.00 Update 3
Microsoft .NET Framework
Version 4.6.01038

インストールしているバージョン:Community

Visual C# 2015 00322-20000-00000-AA575
Microsoft Visual C# 2015

です。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

基本は、絶対にUIの処理はUIのスレッドで行わなくてはならない。
そのため、UIの処理を他スレッドで行わない。そのため、taskの外に出せばいい。

private async void outputExamResultAsync() { IndicatorVisibility = Visibility.Visible; var result = await Task.Run<ResultWindowViewModel>(() => { ResultWindowViewModel resultWindowViewModel = new ResultWindowViewModel(); resultWindowViewModel.重たい処理(); return resultWindowViewModel }); LocatorClass.ShowModalWindow(result); IndicatorVisibility = Visibility.Hidden; }

大体は、そのパターンでできるが、たまにできない時があって、
その時は、UIスレッドを指定して、UIスレッドで実行するということをすればいい。
いろいろと面倒なので、
GalaSoft.MvvmLight.Threading.DispatcherHelper.CheckBeginInvokeOnUI(() => { });
を使うと楽。

投稿2017/06/14 03:01

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cancat

2017/06/14 04:05

いつもありがとうございます。 まだ var result = window.ShowDialog(); でthreadちがうとエラーです。 GalaSoftはNuGet必要でしょうか。今回はNuGet禁止で…。
cancat

2017/06/14 07:39

ありがとうございます。 ちょっとコードが長く、内容のわからないブラックボックスは入れたくないので、これを使うのはまた次回。 結局今回は、できずに時間切れで終了になりました。
guest

0

xaml

1<Window x:Class="pbartest1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:pbartest1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="350" Width="525"> 9 <Grid> 10 <ProgressBar Name="p" HorizontalAlignment="Center" Height="30" VerticalAlignment="Center" Width="300" Margin="105,97,112,192"/> 11 <Button Content="スタート" HorizontalAlignment="Left" Margin="220,193,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="Heaby_Task"/> 12 </Grid> 13</Window>

c#

1using System; 2using System.Threading.Tasks; 3using System.Windows; 4using System.Threading; 5using System.Windows.Threading; 6 7namespace pbartest1 8{ 9 /// <summary> 10 /// MainWindow.xaml の相互作用ロジック 11 /// </summary> 12 public partial class MainWindow : Window 13 { 14 public MainWindow() 15 { 16 InitializeComponent(); 17 timer = new DispatcherTimer(); 18 timer.Interval = TimeSpan.FromSeconds(1); 19 timer.Tick += Check_Count; 20 } 21 22 DispatcherTimer timer; 23 24 void Check_Count(object sender, EventArgs e) 25 { 26 p.Value = p_count; 27 28 if (p.Value == p.Maximum) 29 { 30 MessageBox.Show("作業終了"); 31 p_count = 0; 32 p.Value = 0; 33 timer.Stop(); 34 } 35 } 36 37 public int p_count = 0; 38 39 private async void Heaby_Task(object sender, RoutedEventArgs e) 40 { 41 int i = 5; 42 p.Maximum = i; 43 44 timer.Start(); 45 46 await Task.Run(() => { 47 for (int n = 0; n < i; n++) 48 { 49 System.Threading.Thread.Sleep(4000); 50 p_count++; 51 } 52 }); 53 } 54 } 55}

プログラミング初心者の私の使っている方法です。
カウントを外において、タイマーを使って1秒ごとに確かめて
プログレスバーの値に反映させるというものです。
(質問者様の場合でも正確に動くかどうかは分かりません。)

投稿2017/06/14 04:10

編集2017/06/14 08:28
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cancat

2017/06/14 07:40

コメントありがとうございます。 タイマーも考えたのですが、変更が多いので今回はなしで。 すみません。
退会済みユーザー

退会済みユーザー

2017/06/14 08:46

いえいえ。ご丁寧にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問