Преимущества:
Недостатки:
Лично, я использую их для большей части PK в любой системе достойного размера, но я был "обучен" на системе, которая копировалась повсеместно, таким образом, у нас должны были быть они. YMMV.
я думаю, что дублирующейся вещью данных является мусор - можно получить дублирующиеся данные однако, Вы делаете это. Суррогатные ключи обычно осуждаются, где когда-либо я работал. Мы ДЕЙСТВИТЕЛЬНО используем подобную Wordpress систему хотя:
ОБНОВЛЕНИЕ: , Таким образом, этот получает +1'ed много, и я думал, что должен указать на большую оборотную сторону GUID PK: Кластерные индексы.
, Если у Вас есть много записей и кластерный индекс на GUID, Ваша производительность вставки ВЫСОСЕТ, поскольку Вы добираетесь, вставляет в случайные места в списке объектов (thats точка), не в конце (который быстр)
Поэтому, если Вы должны вставить производительность, возможно, используйте auto-inc INT и генерируйте GUID, если Вы хотите совместно использовать его с кем-то еще (т.е., покажите его пользователю в URL)
If you only use a single thread then the UI will freeze while you do any amount of processing.
If you use a BackgroundWorker thread you'll have more control over what happens & when.
To update the UI you need to use Dispatcher.Invoke
from your background thread to marshal the call across the thread boundary.
Dispatcher.Invoke(DispatcherPriority.Background,
new Action(() => this.TextBlock.Text = "Processing");
Вы можете перевернуть поток управления с ног на голову с помощью DispatcherFrames, позволяя десериализации выполняться в потоке пользовательского интерфейса в фоновом режиме.
Сначала вам нужен способ периодически получать управление во время десериализации. . Независимо от того, какой десериализатор вы используете, он должен будет вызывать наборы свойств для ваших объектов, поэтому вы обычно можете добавлять код в средства установки свойств. В качестве альтернативы вы можете изменить десериализатор. В любом случае убедитесь, что ваш код вызывается достаточно часто
Каждый раз, когда вы получаете управление, все, что вам нужно сделать, это:
. Кроме того, при вызове самого десериализатора убедитесь, что вы делаете это из Dispatcher.BeginInvoke, или что ваш вызывающий код не содержит блокировок и т. д.
Вот как это будет выглядеть:
public partial class MyWindow
{
SomeDeserializer _deserializer = new SomeDeserializer();
byte[] _sourceData;
object _deserializedObject;
...
void LoadButton_Click(...)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
_deserializedObject = _deserializer.DeserializeObject(_sourceData);
}));
}
}
public class OneOfTheObjectsBeingDeserializedFrequently
{
...
public string SomePropertyThatIsFrequentlySet
{
get { ... }
set { ...; BackgroundThreadingSolution.DoEvents(); }
}
}
public class BackgroundThreadingSolution
{
[ThreadLocal]
static DateTime _nextDispatchTime;
public static void DoEvents()
{
// Limit dispatcher queue running to once every 200ms
var now = DateTime.Now;
if(now < _nextDispatchTime) return;
_nextDispatchTime = now.AddMilliseconds(200);
// Run the dispatcher for everything over background priority
var frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
frame.Continue = false;
}));
Dispatcher.PushFrame(frame);
}
}
Проверка DateTime.Now в DoEvents () на самом деле не требуется для работы этого метода, но повысит производительность, если SomeProperty устанавливается очень часто во время десериализации.
Edit: Сразу после того, как я написал это, я понял, что есть более простой способ реализовать метод DoEvents. Вместо использования DispatcherFrame просто используйте Dispatcher.Invoke с пустым действием:
public static void DoEvents()
{
// Limit dispatcher queue running to once every 200ms
var now = DateTime.Now;
if(now < _nextDispatchTime) return;
_nextDispatchTime = now.AddMilliseconds(200);
// Run the dispatcher for everything over background priority
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => {}));
}
Вот замечательная запись в блоге от Dwane Need , в которой обсуждаются все доступные варианты работы с элементами пользовательского интерфейса между несколькими потоками.
Вы действительно не дали достаточно подробностей, чтобы дать хороший рецепт. Например, почему вы вообще сами создаете элементы пользовательского интерфейса, а не используете привязку данных? У вас может быть веская причина, но, не имея более подробной информации, трудно дать хороший совет. В качестве еще одного полезного примера деталей: хотите ли вы построить сложные глубоко вложенные иерархии элементов управления для каждого фрагмента данных или вам просто нужно нарисовать простую фигуру?
Вы по-прежнему можете выполнять долгую обработку в отдельном потоке, но по завершении вам необходимо синхронизироваться с потоком пользовательского интерфейса, вызвав Dispatcher.BeginInvoke (your_UI_action_here)
Рекомендации из блога OldNewThing.
Лучше всего, если вы идете по многопоточному маршруту, чтобы иметь один поток графического интерфейса и порождать вашу рабочую нагрузку в другом потоке, который по завершении сообщает обратно в основной графический интерфейс. нить, что это сделано. Причина этого в том, что вы не столкнетесь с проблемами потоков с вашим графическим интерфейсом.
Итак, One GUI Thread Многие рабочие потоки, которые выполняют эту работу.
Если какой-либо из ваших потоков все же зависает, пользователь, имеющий прямой контроль над вашим приложением, может закрыть поток, не влияя на его опыт работы с интерфейсом приложения. Это сделает его счастливым, потому что ваш пользователь будет чувствовать, что все под контролем, кроме того, что он постоянно нажимает ЭТУ КНОПКУ СТОП, И ПОИСК НЕ ПРЕКРАЩАЕТСЯ.
Попробуйте заморозить ваши UIElements. Замороженные объекты могут передаваться между потоками, не встречая InvalidOperationException, поэтому вы десериализуете их и замораживаете их в фоновом потоке, прежде чем использовать их в своем потоке пользовательского интерфейса.
В качестве альтернативы, рассмотрите возможность отправки отдельных десериализаций обратно в поток пользовательского интерфейса с приоритетом фона. Это не оптимально, поскольку поток пользовательского интерфейса по-прежнему должен выполнять всю работу по десериализации этих объектов, и есть некоторые накладные расходы, добавляемые путем отправки их как отдельных задач, но, по крайней мере, вы не будете блокировать пользовательский интерфейс - события с более высоким приоритетом, такие как ввод можно будет перемежать с вашей работой по десериализации с более низким приоритетом.