gpt4 book ai didi

c# - 防止wpf窗口挂起

转载 作者:太空宇宙 更新时间:2023-11-03 21:59:10 25 4
gpt4 key购买 nike

很抱歉创建另一个主题,因为我的问题不具体且不准确导致线程被关闭和删除。

我有一个聊天应用程序,我希望我的应用程序不会在聊天对话的文本 block 每秒刷新一次以检索当前对话时挂起。我怎样才能防止我的应用程序每秒停止和恢复?我实际上使用了谷歌,但作为返回,我没有找到具体的答案。这是我的代码:

    public MainWindow()
{
InitializeComponent();
timerChatRefresh = new DispatcherTimer();
timerChatRefresh.Interval = new TimeSpan(0, 0, 1);
timerChatRefresh.IsEnabled = false;
timerChatRefresh.Tick += new EventHandler(timerChatRefresh_Tick);
timerChatRefresh.Start();
}

void timerChatRefresh_Tick(object sender, EventArgs e)
{
ChatRefresh();
}

private void ChatRefresh()
{
conn = new MySqlConnection("Server=...; Database=...; Uid=...; Password=...;");
ds.Clear();
textBlockChatArea.Text = "";
da.SelectCommand = conn.CreateCommand();
da.SelectCommand.CommandText = "select * from chatmessagetbl";
da.SelectCommand.CommandType = CommandType.Text;
da.Fill(ds, "chatmessagetbl");
foreach (DataRow item in ds.Tables["chatmessagetbl"].Rows)
{
textBlockChatArea.Text += item["username"].ToString() + ": " + item["message"].ToString() + "\n";
}
conn.Dispose();
}

最佳答案

您需要在非 UI 线程的线程上更新文本框。

    Thread chatRefreshTimer;

void StartChat()
{
chatRefreshTimer = new Thread(new ThreadStart(ChatRefresh));
chatRefreshTimer.Start();
}

void ChatRefresh()
{
conn = new MySqlConnection("Server=...; Database=...; Uid=...; Password=...;");
ds.Clear();
da.SelectCommand = conn.CreateCommand();
da.SelectCommand.CommandText = "select * from chatmessagetbl";
da.SelectCommand.CommandType = CommandType.Text;


while (true)
{
da.Fill(ds, "chatmessagetbl");
textBlockChatArea.Text = "";

foreach (DataRow item in ds.Tables["chatmessagetbl"].Rows)
{
//This has to be done on the thread that owns the textbox.
textBlockChatArea.Dispatcher.BeginInvoke(new Action(() =>
{
textBlockChatArea.Text += item["username"].ToString() + ": " + item["message"].ToString() + "\n";
}));
}
Thread.Sleep(TimeSpan.FromSeconds(1));
}
conn.Dispose();
}

我提供的代码不是很干净,它并不是你可以复制和粘贴的最终解决方案(尽管它可能会起作用),它只是试图在正确的方向上帮助你,并且向您展示一种可以使用线程完成的方法。

编辑

为了尝试澄清我在关于使用列表控件而不是文本框的评论中提出的观点,我添加了以下伪程序来尝试解释我的意思。

// Each row returned from the database will be converted in to one of these.
public class ChatEntry
{
public string UserName { get; set; }
public string Message { get; set; }
public int MessageID { get; set; }
}

// You will need to introduce a MessageID field to your database to make this method work.
public partial class MainWindow : Window
{
public ObservableCollection<ChatEntry> Entries
{
get { return (ObservableCollection<ChatEntry>)GetValue(EntriesProperty); }
set { SetValue(EntriesProperty, value); }
}

public static readonly DependencyProperty EntriesProperty = DependencyProperty.Register("Entries", typeof(ObservableCollection<ChatEntry>), typeof(MainWindow), new UIPropertyMetadata(null));

// This will be used to make sure that only new entries are added to the chat log.
int lastMessageID;

// This will be used to call UpdateEntries every second.
Thread updateThread;

public MainWindow()
{
Entries = new ObservableCollection<ChatEntry>();

InitializeComponent();

updateThread = new Thread(new ThreadStart(UpdateEntries));
updateThread.Start();
}

void UpdateEntries()
{
while (true)
{

// Prepare your query to gather messages from the message table
// with MessageID > lastMessageID.

// This bit needs to be done on the UI dispatcher or it'll cause an exception.
this.Dispatcher.BeginInvoke(new Action(() =>
{
// Each row that came back is a new message and can be added to the collection.
foreach (var row in rows)
{
Entries.Add(new ChatEntry()
{
UserName = (string)row["UserName"],
Message = (string)row["Message"],
});
}
}));

// at this point, the UI will have been upadted with JUST the new entries, no flicker
// no scrolling to the top each second.

// just one more thing, we need to set lastMessageID to be the latest messageID
// so next time UpdateEntries is called it'll only get the new ones that we don't
// have yet.
lastMessageID = Entries.Max(x => x.MessageID);

// Sleep for a second to ease the update speed.
Thread.Sleep(1000);
}
}
}

要将列表框绑定(bind)到新的 Entries 属性,您可以在 XAML 中执行类似的操作。

<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<ListView ItemsSource="{Binding Entries}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,0,5,0" FontWeight="Bold" />
<TextBlock Text="{Binding Message}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Window>

关于c# - 防止wpf窗口挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10980050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com