Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Question About C# Delegates

class ClassA
{
public delegate void WriteLog(string msg);
private WriteLog m_WriteLogDelegate;

public ClassA(WriteLog writelog)
{
    m_WriteLogDelegate =  writelog;
    Thread thread = new Thread(new ThreadStart(Search));
    thread.Start();
}

public void Search()
{
    /* ... */
    m_WriteLogDelegate("msg");
    /* ... */
}

}

class classB
{
        private ClassA m_classA;

        protected void WriteLogCallBack(string msg)
        {
            // prints msg
            /* ... */
        }

        public classB()
        {
            m_classA = new ClassA(new WriteLog(WriteLogCallBack));
        }

        public void test1()
        {
            Thread thread = new Thread(new ThreadStart(Run));
            thread.Start();
        }

        public void test2()
        {
            m_classA.Search();
        }

        public void Run()
        {
            while(true)
            {
                /* ... */
                m_classA.Search();
                /* ... */
                Thread.Sleep(1000);
            }
        }
}

Why the following code

ClassB b = new ClassB();
b.test2() 

prints "msg" and this one

ClassB b = new ClassB();
b.test1() 

doesn't print anything?

like image 334
Caner Avatar asked Jun 10 '11 17:06

Caner


2 Answers

Your program likely exits causing the thread to be terminated (or before the thread has time to start). Just as you explicitly created a thread, you need to explicitly wait for the thread to complete!

You need to use Thread.Join or some other method to keep the main program waiting for the thread to complete.

One possible option, using Thread.Join:

public Thread test2()
{
    ...
    return thread;
}

...

b.test2().Join(); // wait for test2 to complete

Another option, using a ManualResetEvent:

class classB
{
    private ManualResetEvent mre = new ManualResetEvent(false);

    ...

    private void Run()
    {
        ...

        this.mre.Set(); // we completed our task
    }

    public void Wait();
    {
        this.mre.WaitOne();
    }

Then your code which call b.test2():

b.test2();
b.Wait();
like image 128
user7116 Avatar answered Sep 28 '22 08:09

user7116


Your code is working for me, although I had to flesh out the parts that were omitted from the post. Unless I did something drastically different from what you're doing, the problem must be somewhere else.

The code below works fine in a console application: I see "Test" printed at 1-second intervals.

internal class ClassA
{
    public WriteLog Log { get; set; }

    public ClassA(WriteLog writeLog)
    {
        Log = writeLog;
    }

    public void Search()
    {
        Log.Print("Test");
    }
}

class classB
{
    private ClassA m_classA;

    protected void WriteLogCallBack(string msg)
    {
        // prints msg
        /* ... */
        Console.WriteLine(msg);
    }

    public classB()
    {
        m_classA = new ClassA(new WriteLog(WriteLogCallBack));
    }



    public void test1()
    {
        Thread thread = new Thread(new ThreadStart(Run));
        thread.Start();
    }

    public void test2()
    {
        m_classA.Search();
    }

    public void Run()
    {
        while (true)
        {
            /* ... */
            m_classA.Search();
            /* ... */
            Thread.Sleep(1000);
        }
    }
}

internal class WriteLog
{
    private Action<string> Callback { get; set; }

    public WriteLog(Action<string> writeLogCallBack)
    {
        Callback = writeLogCallBack;
    }

    public void Print(string msg)
    {
        Callback(msg);
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        classB b = new classB();
        b.test1();
        }
}
like image 36
Adam Lear Avatar answered Sep 28 '22 06:09

Adam Lear