1

Essentially, I have a Do..While loop going through some lines from a text file. I want to process a line, return a value (worked or didn't), then move to the next line.

I have a function called ProcessTXT that accepts 2 strings. Source and Destination of new file.

Is there a way to set a ReturnedValue string = to the result and have the backgroundworker check to see if the variable changed? And if so, add this value to the list box?

private void TranslatePOD(string strSource, string strDest,)
{
  TextWriter tw = new StreamWriter(strDest);
  TextReader tr = new StreamReader(strSource);
  do
    {
      //My Code doing stuff
      //Need to send a result somehow now, but i have more work to do in this loop
      //Then using tw.writeline() to write my results to my new file
    } while (tr.ReadLine() != null);
}

EDIT: Current test code using Yield. My output is "TestingGround.Form1+d__0". Did i do something wrong?

namespace TestingGround
{
public partial class Form1 : Form
{
    static IEnumerable<string> TestYield(string strSource) 
    {
        TextReader tr = new StreamReader(strSource);
        string strCurLine = System.String.Empty;

        while ((strCurLine = tr.ReadLine()) != null)
        {
            yield return strCurLine;
        }
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string MySource = System.String.Empty;
        MySource = @"C:\PODTest\Export Script\Export\Shipment List.csv";
        listBox1.Items.Add(TestYield(MySource));

    }
}
Shifty
  • 13
  • 5
  • 2
    What exactly is the purpose of your code? What are you trying to accomplish? There are several methods for copying/parsing a file... – walther Aug 17 '12 at 19:30
  • http://stackoverflow.com/questions/11270086/what-is-the-use-of-the-yield-keyword-in-c – JonH Aug 17 '12 at 19:31
  • 1
    Well, i am taking an Export CSV from one system, converting to the way our customer needs it, then saving it as ACSII text.. So i need to analyze each line to make sure it is in the correct format, move data around, etc.. – Shifty Aug 17 '12 at 19:31
  • Maybe make a function that processes one line at a time, or call a method that handles your results, you could do this asynchronously. – MrFox Aug 17 '12 at 19:47

2 Answers2

5

Yield is typically used to return results iteratively, or streaming. There are plenty of examples online. There's one on SO for reading in a file.

Community
  • 1
  • 1
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
  • 1
    Yield does not address the cross-thread aspect of the question. – Eric J. Aug 17 '12 at 19:31
  • 1
    @EricJ. - No argument there, though I don't see any particular reason to use a backgroundworker clearly explained in the question so that's the best I can do at this point. Yield gets at the core of the question. Stopping to perform work. – P.Brian.Mackey Aug 17 '12 at 19:35
  • I am looking at your link now. I think I get what Yield is doing. But isnt essentially just taking all of the results and giving them at the end? That may be enough for me. But if i read this right, i dont think this is what i am looking for. – Shifty Aug 17 '12 at 19:39
  • 1
    @Shifty - It doesn't give the results "at the end". It temporarily returns control back to the caller. It works with enumerations (iterating), giving you the power to perform work before "popping the next item off the stack", if you will. It may help to run it through a debugger and see for yourself. – P.Brian.Mackey Aug 17 '12 at 19:45
  • Ok thanks. I will debug a few examples to see how it works. Sorry, rather new to C# if you couldnt tell. – Shifty Aug 17 '12 at 19:47
  • +1 for not addressing the cross-thread aspect! (Much better to stay on one thread unless you've a good reason not to). – Jon Hanna Aug 17 '12 at 20:07
  • @P.Brian.Mackey - This thing is making me feel dumb. I am looking at the examples in your link from SO. I am not getting any compile errors, but it isnt returning what i expected it to. Sorry, added new code to the original question. – Shifty Aug 17 '12 at 20:48
  • @Shifty - yield works with an iterator. Add a forach loop around the listbox. – P.Brian.Mackey Aug 17 '12 at 20:54
  • @P.Brian.Mackey - Just did that... Realized that as I posted the last one... It seems to be returning like it wanted! Now the only questions is, does this work like DoEvents did in VB6? If i was working with a file that had 2000 lines or more, would the program appear locked out? or would the GUI update with the yield? Thanks again. – Shifty Aug 17 '12 at 20:56
  • Long running processes will block the UI. Still need to use typical new thread solution. – P.Brian.Mackey Aug 17 '12 at 20:58
  • @P.Brian.Mackey - Gotcha. But this seems to fit the bill so far. I just needed to get the results while i was in the loop, and this is doing it! Thanks! – Shifty Aug 17 '12 at 21:03
2

It sounds like this is a good case for a producer/consumer queue. C# 4.0 introduced BlockingCollection, which is great for this. Create the blocking collection and ensure that both this process, and whatever needs to consume the results you are passing have access to it. This method can add items to the queue, and whatever is reading the results can use the Take method, which will block [wait] until there is at least one item to take out. The collection is specifically designed to work in multithreaded environments; all of the operations are logically atomic.

Servy
  • 202,030
  • 26
  • 332
  • 449