У меня есть приложение WPF, подключенное к SQL Server; пока я загружаю в свой DataGrid до 10 записей, мое приложение работает нормально, а ответ слишком быстрый, но когда я загружаю все строки (а это почти 1000), моему приложению потребовалось около 15 секунд для загрузки и зависания всего пользовательского интерфейса.
Но когда я выполняю тот же запрос в SQL Server, загрузка этих 1000 строк занимает всего около 00: 00: 00,490 секунд, что слишком быстро. Я уже сделал следующее, чтобы избежать зависания пользовательского интерфейса и быстрого выполнения запросов. Что я делаю не так? Пожалуйста, помогите с фрагментами кода, так как я новичок в мире C#.
// Calling function to load data into DataGrid in a new thread,
// to make UI responsive.
String qry = "select * from institutes_tbl"
DataGrid dg = MainDataGrid;
Thread thread = new Thread(() => FunDataGrid_DataView(dg, qry));
thread.IsBackground = true;
thread.Start();
Но, к сожалению, в моем интерфейсе отображается сообщение «Не отвечает». Ниже приведено определение функции:
public void FunDataGrid_DataView(DataGrid dg, string qry)
{
Application.Current.Dispatcher.BeginInvoke
(
DispatcherPriority.Background,
new Action(() =>
{
try
{
con = new SqlConnection(con_string);
cmd = new SqlCommand(qry, con);
cmd.CommandTimeout = 12 * 3600;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
dg.ItemsSource = dt.DefaultView;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
));
}
Вот мой XAML:
<DataGrid x:Name = "DataGrid_View"
MouseLeftButtonUp = "DataGrid_View_MouseLeftButtonUp"
ItemsSource = "{Binding DATA_TBL}"
LoadingRow = "DataGrid_View_LoadingRow" Grid.Row = "2"
Grid.Column = "0" ScrollViewer.CanContentScroll = "False"
AutoGenerateColumns = "False" CanUserAddRows = "False"
Background = "#7F179DB2" CellStyle = "{StaticResource CellStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header = "Name"
Binding = "{Binding NAME}" Width = "5*"/>
<DataGridTextColumn Header = "Father Name"
Binding = "{Binding F_NAME}" Width = "5*"/>
<DataGridTextColumn Header = "CNIC"
Binding = "{Binding CNIC}" Width = "5*"/>
</DataGrid.Columns>
</DataGrid>
Я хочу, чтобы мой пользовательский интерфейс был отзывчивым, а данные загружались быстро. Я сейчас работаю на локальном хосте.
вам нужны все столбцы? Если нет, то укажите только эти столбцы в предложении select. Также назначьте сетку данных без потоковой передачи
@ S.Akbari Поскольку я также использую Диспетчер и Новую тему Что я делаю не так? Не могли бы вы рассказать немного больше? Я перешел по указанной вами ссылке.
@SatishPai Да! Мне нужны целые данные по всем столбцам.
Да, вы создаете новый поток, но затем снова выполняете фактический доступ к базе данных в потоке пользовательского интерфейса (Application.Current.Dispatcher)
у вас есть сетка данных внутри средства просмотра прокрутки в xaml?
@ KlausGütter, но если я не использую диспетчер, он говорит: «Вызывающий поток не может получить доступ к этому объекту, потому что он принадлежит другому потоку» Что мне делать для этого?
@SatishPai Нет, в моей сетке данных нет средства просмотра прокрутки.
Application.Current ... хм ... это основной поток пользовательского интерфейса, в который вы отправляете. Вероятно, объясняет, почему UI зависает: поток, который управляет ответами UI на действия пользователя, занят выполнением работы SQL. По какой-то причине? Обычно вы хотите вызвать основной поток пользовательского интерфейса только для принудительного обновления контекста и, используя концепции MVVM, это означает, что вы выполняете то, что называется вызовом INPC (INotifyPropertyChanged). Используйте этот поток для обновления класса viewmodel, который реализует INPC, и вы должны вернуться на «счастливый путь» WPF.
Несвязанные советы: SqlConnection SqlCommand и SqlDataAdapter - все IDisposable, поэтому каждый должен быть в блоке using.
@ code4life Я не реализовал MVVM, но это простое приложение
Убедитесь, что вы каким-то образом не отключили виртуализацию пользовательского интерфейса. Пожалуйста, опубликуйте свой XAML для получения дополнительной помощи.
@ mm8 Я обновил свой вопрос и разместил свой XAML, пожалуйста, посмотрите.
Попробуйте указать фактическую высоту Datagrid. Проблема здесь, похоже, в том, что вы даете своей сетке данных достаточно места для рендеринга каждого элемента без виртуализации. Поэтому попробуйте поместить его, например, в сетку с определением строки размером 400 и проверьте, загружается ли пользовательский интерфейс быстрее.





Попробуй это:
public void FunDataGrid_DataView(DataGrid dg, string qry)
{
con = new SqlConnection(con_string);
cmd = new SqlCommand(qry, con);
cmd.CommandTimeout = 12 * 3600;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() =>
{
try
{
dg.ItemsSource = dt.DefaultView;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}));
}
Надеюсь, поможет!
К сожалению, у меня это не сработало! Проблема все еще существует, мой пользовательский интерфейс зависает и перестает отвечать, пока данные не будут загружены в DataGrid. После этого все перешло в нормальное состояние.
Запустите новый фоновый поток для запроса данных из таблицы, как показано ниже:
Task.Factory.StartNew(() =>
{
try
{
con = new SqlConnection(con_string);
cmd = new SqlCommand(qry, con);
cmd.CommandTimeout = 12 * 3600;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
Application.Current.Dispatcher.BeginInvoke
(
DispatcherPriority.Background,
new Action(() => dg.ItemsSource = dt.DefaultView)
);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error!", MessageBoxButton.OK,
MessageBoxImage.Warning);
}
});
Спасибо за ответ @RajN, но, к сожалению, это решение также не работает, мой пользовательский интерфейс все еще зависает. Я обнаружил проблему, которая находится в этой строке dg.ItemsSource = dt.DefaultView, если я прокомментирую, все работает нормально, поэтому причина в загрузке данных из таблица данных в DataGrid замораживает мой пользовательский интерфейс, я не знаю, как с этим справиться.
@ asim.ali314 Предоставьте образец одной строки данных. Я считаю, что этот ответ должен помочь.
У меня 25 столбцов в таблице, каждая таблица имеет тип от VARCHAR (250) до VARCHAR (1000), поскольку данные содержат много деталей. Может быть, это поможет? Более того, мои данные содержат только текст.