提问人:McStar 提问时间:11/16/2023 更新时间:11/20/2023 访问量:54
为什么线程只运行一次 - 打开和关闭窗口?
Why does the thread run only once - open and close windows?
问:
我正在尝试在登录程序时打开“加载”窗口。一切只正常工作一次。第二次运行它时,出现错误:System.InvalidOperationException:调用线程无法访问此对象,因为它属于另一个线程。请帮忙...
视图模型 .cs
private ProszeCzekaj proszeCzekaj;
private async void ZalogujExecute(object obj)
{
try
{
Thread tbr = new Thread(() =>
{
proszeCzekaj = new ProszeCzekaj();
proszeCzekaj.Closed += (sender2, e2) =>
proszeCzekaj.Dispatcher.InvokeShutdown();
proszeCzekaj.Show();
Dispatcher.Run();
});
tbr.SetApartmentState(ApartmentState.STA); //required for WPF
tbr.Start();
var odp = await SprawdzLogowanie();
if (odp==1)
{
}
proszeCzekaj.Dispatcher.Invoke(proszeCzekaj.Window2Close);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
async Task<int> SprawdzLogowanie()
{
await Task.Run(() =>
{
AplikacjaDbContext db = new AplikacjaDbContext();
foreach (var user in db.UsersTable.ToList())
{
MessageBox.Show(user.userLogin); //for test
}
});
return 1;
}
Logowanie.xaml.cs
namespace PGSQL.View
{
/// <summary>
/// Logika interakcji dla klasy Logowanie.xaml
/// </summary>
public delegate void dWindow2Close();
public partial class Logowanie : Window
{
public Logowanie()
{
InitializeComponent();
LogowanieViewModel model = new LogowanieViewModel();
this.DataContext = model;
}
}
}
加载.xaml.cs
namespace PGSQL.View
{
/// <summary>
/// Logika interakcji dla klasy ProszeCzekaj.xaml
/// </summary>
public partial class ProszeCzekaj : Window
{
public dWindow2Close Window2Close;
public ProszeCzekaj()
{
InitializeComponent();
Window2Close = new dWindow2Close(SecondWindowClose);
IntPtr hWnd = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
var attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE;
var preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND;
DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint));
ProszeCzekajViewModel model = new ProszeCzekajViewModel();
this.DataContext = model;
}
private void SecondWindowClose()
{
this.Close();
}
public enum DWMWINDOWATTRIBUTE
{
DWMWA_WINDOW_CORNER_PREFERENCE = 33
}
// The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function
// what value of the enum to set.
// Copied from dwmapi.h
public enum DWM_WINDOW_CORNER_PREFERENCE
{
DWMWCP_DEFAULT = 0,
DWMWCP_DONOTROUND = 1,
DWMWCP_ROUND = 2,
DWMWCP_ROUNDSMALL = 3
}
// Import dwmapi.dll and define DwmSetWindowAttribute in C# corresponding to the native function.
[DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
internal static extern void DwmSetWindowAttribute(IntPtr hwnd,
DWMWINDOWATTRIBUTE attribute,
ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
uint cbAttribute);
}
}
答:
0赞
SmellyCat
11/20/2023
#1
如果重用 Show 方法,预计会引发异常。
在正在关闭 (Closesing) 或已关闭 (Closed) 的窗口上调用 InvalidOperationException
Show()。
如果要重用窗口,最好:
- 调用隐藏而不是
SecondWindowClose
Close
- 为了防止用户关闭,也许使用 WindowStyle
ProszeCzekaj
上一个:增加线程数会使程序变慢
评论
tbr.IsBackground = true;
tbr.Start();
proszeCzekaj.Show();
ZalogujExecute
> PGSQL.exe!PGSQL::ViewModel::LogowanieViewModel::<<ZalogujExecute>b__33_0>d::MoveNext()
proszeCzekaj.Show();
ZalogujExecute
public PGSQLCommand Zaloguj { get; set; }
Zaloguj = new PGSQLCommand(ZalogujExecute, ZalogujCanExecute);
private void Zaloguj_Click(object sender, RoutedEventArgs e) { Thread tbr = new Thread(() => { br = new ProszeCzekaj(); br.Closed += (sender2, e2) => br.Dispatcher.InvokeShutdown(); br.Show(); System.Windows.Threading.Dispatcher.Run(); }); tbr.SetApartmentState(ApartmentState.STA); //required for WPF tbr.Start(); } private void Anuluj_Click(object sender, RoutedEventArgs e) { br.Dispatcher.Invoke(br.Window2Close); }