C99 N1256 стандартная черновик
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
6.5.3.4 Оператор sizeof :
3 При применении к операнду, который имеет структуру или тип объединения, результатом является общее количество байтов в таких объект, включая внутреннюю и конечную прокладку.
blockquote>6.7.2.1 Спецификаторы структуры и объединения :
13 ... Там может быть неназванным дополнением внутри объекта структуры, но не в начале.
blockquote>и:
15 В конце структуры может быть неназванное дополнение или объединение.
blockquote>Новая функция члена C99 с гибким элементом массива (
struct S {int is[];};
) также может влиять на заполнение:16 As в специальном случае последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; это называется гибким элементом массива. В большинстве ситуаций гибкий элемент массива игнорируется. В частности, размер структуры выглядит так, как если бы гибкий элемент массива был пропущен, за исключением того, что он мог иметь более длинное дополнение, чем подразумевалось.
blockquote>Приложение J Проблемы с переносимостью повторяет:
Следующие неуказаны: ...
blockquote>
- Значение байтов заполнения при хранении значений в структурах или объединениях (6.2.6.1)
C ++ 11 Стандартная черновая версия N3337
http://www.open-std.org/jtc1/sc22/wg21/ docs / papers / 2012 / n3337.pdf
5.3.3 Размер :
2 При применении к классу результатом является количество байтов в объекте этого класса, включая любое дополнение, необходимое для размещения объектов этого типа в массиве.
blockquote>9.2 Члены класса :
Указатель на объект структуры стандартного макета, соответствующим образом преобразованный с использованием reinterpret_cast, указывает на его начальный член (или если этот элемент является битовым полем, то t o единица, в которой он находится) и наоборот. [Примечание. Таким образом, в рамках объекта структуры стандартного макета может быть указано неназванное заполнение, но не в его начале, по мере необходимости, для достижения соответствующего выравнивания. - end note]
blockquote>Я знаю достаточно C ++, чтобы понять примечание: -)
Вот пример кода для Системы. ComponentModel. Класс BackgroundWorker.
private static BackgroundWorker worker = new BackgroundWorker();
static void Main(string[] args)
{
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.ProgressChanged += worker_ProgressChanged;
worker.WorkerReportsProgress = true;
Console.WriteLine("Starting application.");
worker.RunWorkerAsync();
Console.ReadKey();
}
static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("Progress.");
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Starting doing some work now.");
for (int i = 0; i < 5; i++)
{
Thread.Sleep(1000);
worker.ReportProgress(i);
}
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("Done now.");
}
Я комбинирую несколько ответов здесь.
Идеальная ситуация использует ориентированный на многопотоковое исполнение флаг такой в качестве AutoResetEvent
. Вы не должны блокироваться неограниченно долго, когда Вы звоните WaitOne()
, на самом деле это имеет перегрузку, которая позволяет Вам указывать тайм-аут. Эта перегрузка возвраты false
если флаг не был установлен во время интервала.
A Queue
более идеальная структура для отношений производителя/потребителя, но можно подражать ему, если требования вынуждают Вас использовать a List
. Существенное различие, Вы оказываетесь перед необходимостью удостоверяться, что Ваш потребитель блокирует доступ к набору, в то время как это извлекает объекты; самая безопасная вещь состоит в том, чтобы, вероятно, использовать CopyTo
метод для копирования всех элементов в массив затем выпустите блокировку. Конечно, удостоверьтесь, что Ваш производитель не попытается обновить List
в то время как блокировка сохранена.
Вот простое консольное приложение C#, которое демонстрирует, как это могло бы быть реализовано. Если Вы играете вокруг с интервалами синхронизации, можно вызвать различные вещи произойти; в этой конкретной конфигурации я пытался сделать, чтобы производитель генерировал несколько объектов перед потребительскими проверками на объекты.
using System;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private static object LockObject = new Object();
private static AutoResetEvent _flag;
private static Queue<int> _list;
static void Main(string[] args)
{
_list = new Queue<int>();
_flag = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(ProducerThread);
int itemCount = 0;
while (itemCount < 10)
{
if (_flag.WaitOne(0))
{
// there was an item
lock (LockObject)
{
Console.WriteLine("Items in queue:");
while (_list.Count > 0)
{
Console.WriteLine("Found item {0}.", _list.Dequeue());
itemCount++;
}
}
}
else
{
Console.WriteLine("No items in queue.");
Thread.Sleep(125);
}
}
}
private static void ProducerThread(object state)
{
Random rng = new Random();
Thread.Sleep(250);
for (int i = 0; i < 10; i++)
{
lock (LockObject)
{
_list.Enqueue(rng.Next(0, 100));
_flag.Set();
Thread.Sleep(rng.Next(0, 250));
}
}
}
}
}
Если Вы не хотите блокировать производителя вообще, это немного более хитро. В этом случае я предложил бы делать производителя его собственным классом и с частным и с общедоступным буфером и общественностью AutoResetEvent
. Производитель будет объектами хранилища по умолчанию в частном буфере, затем пытаться записать им в общедоступный буфер. Когда потребитель работает с общедоступным буфером, он сбрасывает флаг на объекте производителя. Прежде чем производитель пытается переместить объекты с частного буфера на общедоступный буфер, он проверяет этот флаг и только копирует объекты, когда потребитель не работает над ним.
Если Вы используете backgroundworker, чтобы запустить второй поток и использовать событие ProgressChanged, чтобы уведомить другой поток, что данные готовы. Другие события доступны также. Эта статья MSDN должна запустить Вас.
Существует много способов сделать это, в зависимости от точно, что Вы хотите сделать. Очередь производителя/потребителя, вероятно, что Вы хотите. Для превосходного всестороннего взгляда в потоки см. главу по Поточной обработке (доступный онлайн) от превосходного книжного C# 3.0 вкратце.
Можно использовать AutoResetEvent (или ManualResetEvent). Если Вы используете AutoResetEvent. WaitOne (0, ложь), это не заблокируется. Например:
AutoResetEvent ev = new AutoResetEvent(false);
...
if(ev.WaitOne(0, false)) {
// event happened
}
else {
// do other stuff
}
Класс BackgroundWorker является ответом в этом случае. Это - единственная конструкция поточной обработки, которая может асинхронно отправить сообщения в поток, который создал объект BackgroundWorker. Внутренне BackgroundWorker
использование AsyncOperation
класс путем вызова asyncOperation.Post()
метод.
this.asyncOperation = AsyncOperationManager.CreateOperation(null);
this.asyncOperation.Post(delegateMethod, arg);
Несколько других классов в платформе.NET также используют AsyncOperation:
Если Ваш "основной" поток является насосом сообщения Windows (GUI) поток, то можно опросить использование Формы. Таймер - настраивает интервал таймера согласно тому, как быстро у Вас должно быть свое 'уведомление' потока GUI данные из рабочего потока.
Не забудьте синхронизировать доступ к общему List<>
если Вы собираетесь использовать foreach
, избегать CollectionModified
исключения.
Я использую эту технику для всех управляемых данными рынком обновлений GUI в торговом приложении в реальном времени, и она работает очень хорошо.