How to make a function that blocks until it has data to return in c#
Asked Answered
C

2

3

How do I make a custom function that returns output and blocks until output is available? I'm thinking of something like Console.ReadLine(). Something like this:

var resp = Output(); //blocks until output is sent.
...
//returns a string once SendOutput is called and hands over the string.
public static string Output() { /* what goes here? */ }
//Is this function even needed? Can I just fire Output somehow?
private static string SendOutput(string msg) { /* what goes here? */ }
...
//Calls sendoutput with the string to send.
SendOutput(msg);

Basically I'm making a listener that is blocked until it gets data (like it would if calling console.readline), and I need the internal code to make the blocker.

Cyprinid answered 5/10, 2012 at 1:29 Comment(4)
One of the two is to be input, not output (for input of one is the output of the other), right?Chromaticness
It's all internal, thus the anomaly. I changed SendOutput to private. Hopefully that will clarify it.Cyprinid
this sounds like a case where you'd want to use events, however you'd need to expand a little more on exactly what you're trying to do...Glacialist
I'm making a listener that is blocked until it gets data (like console.readline), and I need the internal code to make the blocker. I figured events would probably be the answer but I don't know how.Cyprinid
B
4

What you want is for your blocking method call to be signalled when some other work has completed. A ManualResetEvent is a good way to achieve this behaviour; there are no loops, and the return is virtually instantaneous once the worker thread signals that it is complete.

class Program
{
    static void Main(string[] args)
    {
        Blocker b = new Blocker();
        Console.WriteLine(b.WaitForResult());
    }
}

public class Blocker
{
    private const int TIMEOUT_MILLISECONDS = 5000;
    private ManualResetEvent manualResetEvent;

    private string output;

    public string WaitForResult()
    {
        // create an event which we can block on until signalled
        manualResetEvent = new ManualResetEvent(false);

        // start work in a new thread
        Thread t = new Thread(DoWork);
        t.Start();

        // block until either the DoWork method signals it is completed, or we timeout (timeout is optional)
        if (!manualResetEvent.WaitOne(TIMEOUT_MILLISECONDS))
            throw new TimeoutException();

        return output;
    }

    private void DoWork()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++)
        {
            sb.AppendFormat("{0}.", i);
        }
        output = sb.ToString();

        // worker thread is done, we can let the WaitForResult method exit now
        manualResetEvent.Set();
    }
}
Bellbella answered 5/10, 2012 at 2:12 Comment(2)
Also, could this be called from multiple methods and return the same thing to all of them?Cyprinid
If you use AutoResetEvent, it will...well...Auto Reset :)Cyprinid
U
-1

threaded process call and use background worker to notify back when data is available.

private void Create_Thread()
{
    //Parameterized function
    Thread wt = new Thread(new ParameterizedThreadStart(this.DoWork));
    wt.Start([/*Pass parameters here*/]);
}

public void DoWork(object data)
{
    Thread.Sleep(1000);
    //Process Data - Do Work Here

    //Call Delegate Method to Process Result Data
    Post_Result(lvitem);
}

private delegate void _Post_Result(object data);

private void Post_Result(object data)
{
    //Process Result
}
Unlucky answered 5/10, 2012 at 1:51 Comment(3)
Where is the blocker? I need a method that waits to return a value until it is given something to return.Cyprinid
do you intend to make the main application process to hang?Unlucky
var result = ConsoleReadLineLikeMethodToReturnData();. Yes, do you know how Console.ReadLine() works? I think stream readers are the same way.Cyprinid

© 2022 - 2024 — McMap. All rights reserved.