Темы и делегаты - я не совсем понимаю их отношения

Я написал код, который выглядит примерно так:

Thread t = new Thread(() => createSomething(dt, start, finish) );
t.Start();

И это работает (иногда кажется, что есть несколько потоков).

Пока я не использую никаких делегатов.

В чем смысл протектора без делегата?Если делегат нужен - тогда, пожалуйста, скажите мне, что и как делается с делегатом.

Ответы на вопрос(2)

Выявляются использование делегата - это просто синтаксический сахар C # для:

Thread t = new Thread(new ThreadStart( () => createSomething(dt, start, finish))); 
t.Start();

Компиляторвыводя от лямбда-выражения и различных перегрузок, которыеThread у конструктора есть намерение:

Создать экземплярThreadStart делегировать.Передайте его в качестве аргумента перегрузке конструктораThread который принимаетThreadStart объект.

Вы также можете эквивалентно написать это с синтаксисом анонимного делегата:

 Thread t = new Thread(delegate() { createSomething(dt, start, finish); } ); 
 t.Start();

Если аргументыcreateSomething не являются (захваченными) местными жителями, вы могли бы написать это вообще без анонимных методов, что должно более четко выделить создание делегата:

private void Create()
{
   createSomething(dt, start, finish))); 
}

...

Thread t = new Thread(new ThreadStart(Create)); //new ThreadStart is optional for the same reason 
t.Start();
 Ani25 сент. 2010 г., 14:17
@Maciej Hehl: 1. Скобки и точки с запятой являются необязательными. 2. Выражения Lamba всегда могут заменить анонимных делегатов.
 Maciej Hehl25 сент. 2010 г., 14:08
Лямбда() => createSomething(dt, start, finish) эквивалентноnew delegate() { return createSomething(dt, start, finish); }, Если делегат возвращаетсяvoid Лямбда не должна выглядеть так:() => {createSomething(dt, start, finish);}? Другое дело, если использование такой лямбды здесь законно.
 Ani25 сент. 2010 г., 14:57
Да, это,ThreadStart объявлен как:public delegate void ThreadStart(); Вот что делает это необязательным в этом случае.
 Asaf25 сент. 2010 г., 11:00
Спасибо, красивые вещи случаются, когда вы копируете код от умных людей, но этот «сахар» скрывает «нормальный» путь от меня ... Я не объявляю делегата и, конечно, не понимаю, как он работает ... Так что вы помог мне понять, что моя программа работает - потому что она написана правильно, но я не понимаю, что происходит под капотом ... что мне действительно нужно, это общий \ пример не "сахара" для "вызова функции без param 'и' вызов функции с params '
 Maciej Hehl25 сент. 2010 г., 14:39
Это не просто необязательно. Первый - это выражение лямбда, а второй - выражение лямбда. Это два типа лямбд, и есть некоторые ограничения на использование некоторых типов в некоторых обстоятельствах. Одним из них является то, что лямбда-выражения нельзя использовать для создания деревьев выражений, но я не помню, есть ли другие. Может быть, утверждение лямбда здесь законно. ЕслиcreateSomething возвращает void, они могут быть эквивалентны, но так ли это?
Решение Вопроса

Многопоточность очень сложна. Вы вырезаете и вставляете код, даже не изучая ничего о самых основных аспектах многопоточности - как запустить поток. Вставка чего-либо из Интернета в пользовательский интерфейс для исправления или настройки элемента управления - это одно. Это совершенно другой процесс. Вам нужно изучить предмет, написать весь собственный код и точно понять, как он работает, иначе вы просто тратите время на это.

Делегат - это .NET-версия указателя безопасной функции типа. Все потоки требуют точки входа, чтобы начать выполнение. По определению, когда создается первичный поток, он всегда запускает Main () в качестве своей точки входа. Любые дополнительные потоки, которые вы создадите, будут нуждаться в явно определенной точке входа - указателе на функцию, с которой они должны начать выполнение. Таким образом, потоки всегда требуют делегата.

Делегаты часто используются в потоках и для других целей, в основном для обратных вызовов. Если вы хотите, чтобы поток сообщал некоторую информацию, такую ​​как состояние завершения, одной из возможностей является создание функции обратного вызова, которую этот поток может использовать. Снова потоку нужен указатель, чтобы иметь возможность выполнить обратный вызов, поэтому делегаты также используются для этого. В отличие от точки входа они являются необязательными, но концепция та же.

Отношения между потоками и делегатами - это вторичные потоки, которые не могут просто вызывать методы, подобные первичному потоку приложения, поэтому вместо них необходим указатель на функцию, а делегаты действуют как указатели на функции.

Вы не видите делегата и не создали его, потому что фреймворк делает это за вас в конструкторе Thread. Вы можете передать метод, который хотите использовать для запуска потока, и код платформы создаст делегат, который указывает на этот метод для вас. Если вы хотите использовать обратный вызов, вам придется создать делегата самостоятельно.

Вот код без лямбда-выражений. SomeClass имеет некоторую обработку, которая занимает много времени и выполняется в фоновых потоках. Чтобы помочь с этим, был создан SomeThreadTask, который содержит код процесса и все, что потоку нужно для его запуска. Второй делегат используется для обратного вызова, когда поток завершен.

Реальный код будет более сложным, и реальный класс никогда не должен будет знать, как создавать потоки и т. Д., Чтобы у вас были объекты менеджера.

// Create a delegate for our callback function.
public delegate void SomeThreadTaskCompleted(string taskId, bool isError);


public class SomeClass
{

    private void DoBackgroundWork()
    {
        // Create a ThreadTask object.

        SomeThreadTask threadTask = new SomeThreadTask();

        // Create a task id.  Quick and dirty here to keep it simple.  
        // Read about threading and task identifiers to learn 
        // various ways people commonly do this for production code.

        threadTask.TaskId = "MyTask" + DateTime.Now.Ticks.ToString();

        // Set the thread up with a callback function pointer.

        threadTask.CompletedCallback = 
            new SomeThreadTaskCompleted(SomeThreadTaskCompletedCallback);


        // Create a thread.  We only need to specify the entry point function.
        // Framework creates the actual delegate for thread with this entry point.

        Thread thread = new Thread(threadTask.ExecuteThreadTask);

        // Do something with our thread and threadTask object instances just created
        // so we could cancel the thread etc.  Can be as simple as stick 'em in a bag
        // or may need a complex manager, just depends.

        // GO!
        thread.Start();

        // Go do something else.  When task finishes we will get a callback.

    }

    /// <summary>
    /// Method that receives callbacks from threads upon completion.
    /// </summary>
    /// <param name="taskId"></param>
    /// <param name="isError"></param>
    public void SomeThreadTaskCompletedCallback(string taskId, bool isError)
    {
        // Do post background work here.
        // Cleanup the thread and task object references, etc.
    }
}


/// <summary>
/// ThreadTask defines the work a thread needs to do and also provides any data 
/// required along with callback pointers etc.
/// Populate a new ThreadTask instance with any data the thread needs 
/// then start the thread to execute the task.
/// </summary>
internal class SomeThreadTask
{

    private string _taskId;
    private SomeThreadTaskCompleted _completedCallback;

    /// <summary>
    /// Get. Set simple identifier that allows main thread to identify this task.
    /// </summary>
    internal string TaskId
    {
        get { return _taskId; }
        set { _taskId = value; }
    }

    /// <summary>
    /// Get, Set instance of a delegate used to notify the main thread when done.
    /// </summary>
    internal SomeThreadTaskCompleted CompletedCallback
    {
        get { return _completedCallback; }
        set { _completedCallback = value; }
    }

    /// <summary>
    /// Thread entry point function.
    /// </summary>
    internal void ExecuteThreadTask()
    {
        // Often a good idea to tell the main thread if there was an error
        bool isError = false;

        // Thread begins execution here.

        // You would start some kind of long task here 
        // such as image processing, file parsing, complex query, etc.

        // Thread execution eventually returns to this function when complete.

        // Execute callback to tell main thread this task is done.
        _completedCallback.Invoke(_taskId, isError);


    }

}
}
 Asaf25 сент. 2010 г., 23:19
Сначала я ценю ваш подробный ответ. Я не спешу выучить это внимательно. О копировании и вставке ... Иногда футболист, который изучает свой футбол в окрестностях, а затем совершенствуется в хорошем клубе, лучше, чем тот, который вырос в клубе. Другими словами, иногда нужно что-то почувствовать, прежде чем понять. Во всяком случае ... Вы помогли мне, и я благодарю вас за это

Ваш ответ на вопрос