问:
Why won't my while loop if condition work correctly?
My checkWin method returns false until there's a winner in the Connect 4 game by putting 4 "checkers" in a row horizontally, vertically, or diagonally in my board array. Once there's a winner, the checkWin method returns true, the nearest if statement iterates, printing the winner, then terminating the entire loop (if I coded it all correctly). However, when I run the program, the while loop iterates only once, accepts one input for red, states red won, then does the same thing for yellow, then terminates.

What am I missing here?

 Below is the relevant code.

Thank you.

```<code>public static void main(String[] args) {
    char[][] board = new char[6][7];
    boolean loop = true;
    // loop to alternate players until there's a winner
    while (loop) {
        printData(board);
        red(board);
        if (checkWin(board) == true) {
            printData(board);
            System.out.print("Red wins!");
            loop = false;
        }
        printData(board);
        yellow(board);
        if (checkWin(board) == true) {
            printData(board);
            System.out.print("Yellow wins!");
            loop = false;
        }
    }
}

public static void printData(char[][] tbl) {
    for (int r = 0; r < tbl.length; r++) {
        for (int c = 0; c < tbl[r].length; c++) {
            if (tbl[r][c] == 0) {
                System.out.print("| ");
            } else {
                System.out.print("|" + tbl[r][c]);
            }
        } // end for col loop
        System.out.println("|");
    } // end for row loop
    System.out.println("---------------");
} // end printData method

public static void red(char[][] f) {
    System.out.println("Place a red checker at column (0-6)");
    Scanner in = new Scanner(System.in);
    int c = in.nextInt();
    for (int i = 5; i >= 0; i--) {
        if (f[i][c] == 0) {
            f[i][c] = 'R';
            break;
        }
    }
}

public static void yellow(char[][] f) {
    System.out.println("Place a yellow checker at column (0-6)");
    Scanner in = new Scanner(System.in);
    int c = in.nextInt();
    for (int i = 5; i >= 0; i--) {
        if (f[i][c] == 0) {
            f[i][c] = 'Y';
            break;
        }
    }
}

// Method to check for a winner. Receives 2-D array as parameter. Returns
// boolean value.
public static boolean checkWin(char[][] b) {
    // Create four boolean variables, one for each set of rows. Initialize
    // all of them to false.
    boolean foundRow = false;
    boolean foundCol = false;
    boolean foundMjrD = false;
    boolean foundMinD = false;

    // Check to see if four consecutive cells in a row match.
    // check rows
    for (int r = 0; r <= 5; r++) {
        for (int c = 0; c <= 3; c++) {
            if (b[r][c] == b[r][c + 1] && b[r][c] == b[r][c + 2] && b[r][c] == b[r][c + 3] && b[r][c] != ' ') {
                foundRow = true;
                break;
            }
        }
    }

    // Check to see if four columns in the same row match
    // check columns
    for (int r = 0; r <= 2; r++) {
        for (int c = 0; c <= 6; c++) {
            if (b[r][c] == b[r + 1][c] && b[r][c] == b[r + 2][c] && b[r][c] == b[r + 3][c] && b[r][c] != ' ') {
                foundCol = true;
                break;
            }
        }
    }

    // Check to see if four diagonals match (top left to bottom right)
    // check major diagonal
    for (int r = 0; r <= 2; r++) {
        for (int c = 0; c <= 3; c++) {
            if (b[r][c] == b[r + 1][c + 1] && b[r][c] == b[r + 2][c + 2] && b[r][c] == b[r + 3][c + 3]
                    && b[r][c] != ' ') {
                foundMjrD = true;
                break;
            }
        }
    }

    // Check to see if four diagonals in the other direction match (top
    // right to bottom left)
    // check minor diagonal
    for (int r = 0; r <= 2; r++) {
        for (int c = 3; c <= 6; c++) {
            if (b[r][c] == b[r + 1][c - 1] && b[r][c] == b[r + 2][c - 2] && b[r][c] == b[r + 3][c - 3]
                    && b[r][c] != ' ') {
                foundMinD = true;
                break;
            }
        }
    }

    // If ONE of the booleans is true, we have a winner.
    // checks boolean for a true
    if (foundRow || foundCol || foundMjrD || foundMinD)
        return true;
    else
        return false;
} // end checkWin method
</code>```

答:
By what I've analyzed by debugging your code , you have not set boolean variable to "true" after toggling it to false. After you are coming out of condition make that boolean variable "true" again.

May this help you. Happy Coding

Body:
My checkWin method returns false until there's a winner in the Connect 4 game by putting 4 "checkers" in a row horizontally, vertically, or diagonally in my board array. Once there's a winner, the checkWin method returns true, the nearest if statement iterates, printing the winner, then terminating the entire loop (if I coded it all correctly). However, when I run the program, the while loop iterates only once, accepts one input for red, states red won, then does the same thing for yellow, then terminates.

What am I missing here?

 Below is the relevant code.

Thank you.

public static void main(String[] args) {
    char[][] board = new char[6][7];
    boolean loop = true;
    // loop to alternate players until there's a winner
    while (loop) {
        printData(board);
        red(board);
        if (checkWin(board) == true) {
            printData(board);
            System.out.print("Red wins!");
            loop = false;
        }
        printData(board);
        yellow(board);
        if (checkWin(board) == true) {
            printData(board);
            System.out.print("Yellow wins!");
            loop = false;
        }
    }
}

public static void printData(char[][] tbl) {
    for (int r = 0; r < tbl.length; r++) {
        for (int c = 0; c < tbl[r].length; c++) {
            if (tbl[r][c] == 0) {
                System.out.print("| ");
            } else {
                System.out.print("|" + tbl[r][c]);
            }
        } // end for col loop
        System.out.println("|");
    } // end for row loop
    System.out.println("---------------");
} // end printData method

public static void red(char[][] f) {
    System.out.println("Place a red checker at column (0-6)");
    Scanner in = new Scanner(System.in);
    int c = in.nextInt();
    for (int i = 5; i >= 0; i--) {
        if (f[i][c] == 0) {
            f[i][c] = 'R';
            break;
        }
    }
}

public static void yellow(char[][] f) {
    System.out.println("Place a yellow checker at column (0-6)");
    Scanner in = new Scanner(System.in);
    int c = in.nextInt();
    for (int i = 5; i >= 0; i--) {
        if (f[i][c] == 0) {
            f[i][c] = 'Y';
            break;
        }
    }
}

// Method to check for a winner. Receives 2-D array as parameter. Returns
// boolean value.
public static boolean checkWin(char[][] b) {
    // Create four boolean variables, one for each set of rows. Initialize
    // all of them to false.
    boolean foundRow = false;
    boolean foundCol = false;
    boolean foundMjrD = false;
    boolean foundMinD = false;

    // Check to see if four consecutive cells in a row match.
    // check rows
    for (int r = 0; r <= 5; r++) {
        for (int c = 0; c <= 3; c++) {
            if (b[r][c] == b[r][c + 1] && b[r][c] == b[r][c + 2] && b[r][c] == b[r][c + 3] && b[r][c] != ' ') {
                foundRow = true;
                break;
            }
        }
    }

    // Check to see if four columns in the same row match
    // check columns
    for (int r = 0; r <= 2; r++) {
        for (int c = 0; c <= 6; c++) {
            if (b[r][c] == b[r + 1][c] && b[r][c] == b[r + 2][c] && b[r][c] == b[r + 3][c] && b[r][c] != ' ') {
                foundCol = true;
                break;
            }
        }
    }

    // Check to see if four diagonals match (top left to bottom right)
    // check major diagonal
    for (int r = 0; r <= 2; r++) {
        for (int c = 0; c <= 3; c++) {
            if (b[r][c] == b[r + 1][c + 1] && b[r][c] == b[r + 2][c + 2] && b[r][c] == b[r + 3][c + 3]
                    && b[r][c] != ' ') {
                foundMjrD = true;
                break;
            }
        }
    }

    // Check to see if four diagonals in the other direction match (top
    // right to bottom left)
    // check minor diagonal
    for (int r = 0; r <= 2; r++) {
        for (int c = 3; c <= 6; c++) {
            if (b[r][c] == b[r + 1][c - 1] && b[r][c] == b[r + 2][c - 2] && b[r][c] == b[r + 3][c - 3]
                    && b[r][c] != ' ') {
                foundMinD = true;
                break;
            }
        }
    }

    // If ONE of the booleans is true, we have a winner.
    // checks boolean for a true
    if (foundRow || foundCol || foundMjrD || foundMinD)
        return true;
    else
        return false;
} // end checkWin method


来源: stackexchange

问:
Using thenAccept after supplyAsync blocks the main thread

I am developing a web application which communicates with other web applications. From time to time, my system sends HTTP request as notification to other systems. Since their responses are not essential to me, I send the requests with Java 8 CompletableFuture supplyAsync and prints their responses with thenAccept so that my main thread will not get blocked. However, I found the CompletableFuture function chains took around 100 to 200 ms each time, which confused me because from my understanding thenAccept() should run in the same thread with supplyAsync()'s.

I mocked my process with below codes

```<code>public static void run() {
    long start = System.currentTimeMillis();
    log.info("run start -> " + new Timestamp(start));
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 42;
    }).thenAccept(res -> log.info("run result -> " + res + ", time -> " + new Timestamp(System.currentTimeMillis())));
    log.info("run duration ->" + (System.currentTimeMillis() - start));
}

public static void runAsync() {
    long start = System.currentTimeMillis();
    log.info("runAsync start -> " + new Timestamp(start));
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 42;
    }).thenAcceptAsync(res -> log.info("runAsync result -> " + res + ", time ->" + new Timestamp(System.currentTimeMillis())));
    log.info("runAsync duration ->" + (System.currentTimeMillis() - start));
}

public static void main(String[] args) throws InterruptedException {
    Test.run();
    Test.runAsync();
    Thread.sleep(1000);
}
</code>```

the run() method uses thenAccept() with supplyAsync() while runAsync() uses thenAcceptAsync(). I expected both of them should take just a few milliseconds. However, the real outputs are:

```<code>10:04:54.632 [main] INFO Test - run start -> 2017-12-08 10:04:54.622
10:04:54.824 [main] INFO Test - run duration ->202
10:04:54.824 [main] INFO Test - runAsync start -> 2017-12-08 10:04:54.824
10:04:54.826 [main] INFO Test - runAsync duration ->2
10:04:55.333 [ForkJoinPool.commonPool-worker-1] INFO Test - run result -> 42, time -> 2017-12-08 10:04:55.333
10:04:55.333 [ForkJoinPool.commonPool-worker-3] INFO Test - runAsync result -> 42, time ->2017-12-08 10:04:55.333
</code>```

We can see run() takes 202 ms which is 100 times of the duration of runAsync() which uses only 2 ms.

I don't understand where is the 202 ms overhead comes from, and obviously it is not the lambda function in supplyAysnc() which sleeps 500 ms.

Could anyone explain why the run() method blocks, and should I always use thenAcceptAsync() over thenAccept() ?

Many thanks.

答:
The 200 ms are startup time for the thread pool and all the classes supporting it.

It becomes obvious if you swap the statements in your main class:

```<code>public static void main(String[] args) throws InterruptedException {
    Test.runAsync();
    Test.run();
    Thread.sleep(1000);
}
</code>```

now Test.runAsync(); is the call that needs 200 ms and Test.run(); completes in 2 ms

ContentLicense: CC BY-SA 3.0

Body:
I am developing a web application which communicates with other web applications. From time to time, my system sends HTTP request as notification to other systems. Since their responses are not essential to me, I send the requests with Java 8 CompletableFuture supplyAsync and prints their responses with thenAccept so that my main thread will not get blocked. However, I found the CompletableFuture function chains took around 100 to 200 ms each time, which confused me because from my understanding thenAccept() should run in the same thread with supplyAsync()'s.

I mocked my process with below codes

public static void run() {
    long start = System.currentTimeMillis();
    log.info("run start -> " + new Timestamp(start));
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 42;
    }).thenAccept(res -> log.info("run result -> " + res + ", time -> " + new Timestamp(System.currentTimeMillis())));
    log.info("run duration ->" + (System.currentTimeMillis() - start));
}

public static void runAsync() {
    long start = System.currentTimeMillis();
    log.info("runAsync start -> " + new Timestamp(start));
    CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 42;
    }).thenAcceptAsync(res -> log.info("runAsync result -> " + res + ", time ->" + new Timestamp(System.currentTimeMillis())));
    log.info("runAsync duration ->" + (System.currentTimeMillis() - start));
}

public static void main(String[] args) throws InterruptedException {
    Test.run();
    Test.runAsync();
    Thread.sleep(1000);
}

the run() method uses thenAccept() with supplyAsync() while runAsync() uses thenAcceptAsync(). I expected both of them should take just a few milliseconds. However, the real outputs are:

10:04:54.632 [main] INFO Test - run start -> 2017-12-08 10:04:54.622
10:04:54.824 [main] INFO Test - run duration ->202
10:04:54.824 [main] INFO Test - runAsync start -> 2017-12-08 10:04:54.824
10:04:54.826 [main] INFO Test - runAsync duration ->2
10:04:55.333 [ForkJoinPool.commonPool-worker-1] INFO Test - run result -> 42, time -> 2017-12-08 10:04:55.333
10:04:55.333 [ForkJoinPool.commonPool-worker-3] INFO Test - runAsync result -> 42, time ->2017-12-08 10:04:55.333

We can see run() takes 202 ms which is 100 times of the duration of runAsync() which uses only 2 ms.

I don't understand where is the 202 ms overhead comes from, and obviously it is not the lambda function in supplyAysnc() which sleeps 500 ms.

Could anyone explain why the run() method blocks, and should I always use thenAcceptAsync() over thenAccept() ?

Many thanks.

Body:
The 200 ms are startup time for the thread pool and all the classes supporting it.

It becomes obvious if you swap the statements in your main class:

public static void main(String[] args) throws InterruptedException {
    Test.runAsync();
    Test.run();
    Thread.sleep(1000);
}

now Test.runAsync(); is the call that needs 200 ms and Test.run(); completes in 2 ms


问:
largest complete subtree in a binary tree
I am defining a complete subtree as a tree with all levels full and the last level left justified i.e. all nodes are as far left as possible, and I want to find the largest subtree in a tree that is complete.

One method is to do the method outlined here for every node as root, which would take O(n^2) time.

Is there a better approach?

答:
I arrived at a solution similar to Mikhail's above (encountered as I go though the EPI book). I've tested it against a few permutations of a complete tree, a perfect tree, a full tree and trees with sub trees that are complete .. but not exhaustively.</p>

```<code>/**
 * Returns the largest complete subtree of a binary tree given by the input node
 *
 * @param root the root of the tree
 */
public int getLargestCompleteSubtree(INode<TKeyType, TValueType> root) {
    max = 0;
    calculateLargestCompleteSubtree(root);

    return max;
}

/**
 * Returns the largest complete subtree of a binary tree given by the input node
 *
 * @param root the root of the tree
 */
public TreeInfo<TKeyType, TValueType> calculateLargestCompleteSubtree(INode<TKeyType, TValueType> root) {
    int size = 0;

    // a complete subtree must have the following attributes
    // 1. All leaves must be within 1 of each other.
    // 2. All leaves must be as far left as possible, i.e, L(child).count() > R(child).count()
    // 3. A complete subtree may have only one node (L child) or two nodes (L, R).

    if (root == null)
    {
        return new TreeInfo<>(true, 0);
    }
    else if (!root.hasLeftChild() && !root.hasRightChild())
    {
        return new TreeInfo<>(true, 1);
    }

    // have children
    TreeInfo<TKeyType, TValueType> leftInfo = calculateLargestCompleteSubtree(root.getLeft());
    TreeInfo<TKeyType, TValueType> rightInfo = calculateLargestCompleteSubtree(root.getRight());

    // case 1: not a complete tree.
    if (!leftInfo.isComplete || !rightInfo.isComplete)
    {
        // Only one subtree is complete. Set it as the max and return false.
        if(leftInfo.isComplete) {
            max = Math.max(max, leftInfo.size);
        }
        else if(rightInfo.isComplete)
        {
            max = Math.max(max, rightInfo.size);
        }

        return new TreeInfo<>(false, -1);
    }

    // case 2: both subtrees complete
    int delta = Math.abs(leftInfo.size - rightInfo.size);
    if (delta <= 1)
    {
        // both are complete but R could be 1 greater...use L tree.
        size = leftInfo.size + 1;
        max = Math.max(max, size);
        return new TreeInfo<>(true, size);
    }
    else
    {
        // limit to size of R + 1 if L - R > 1, otherwise L
        if(leftInfo.size > rightInfo.size)
        {
            max = Math.max(max, leftInfo.size);
            size = rightInfo.size + 1;
        }
        else
        {
            max = Math.max(max, rightInfo.size);
            size = leftInfo.size;
        }

        return new TreeInfo<>(true, size + 1);
    }
}
</code>```

Body:
I arrived at a solution similar to Mikhail's above (encountered as I go though the EPI book). I've tested it against a few permutations of a complete tree, a perfect tree, a full tree and trees with sub trees that are complete .. but not exhaustively.

/**
 * Returns the largest complete subtree of a binary tree given by the input node
 *
 * @param root the root of the tree
 */
public int getLargestCompleteSubtree(INode<TKeyType, TValueType> root) {
    max = 0;
    calculateLargestCompleteSubtree(root);

    return max;
}

/**
 * Returns the largest complete subtree of a binary tree given by the input node
 *
 * @param root the root of the tree
 */
public TreeInfo<TKeyType, TValueType> calculateLargestCompleteSubtree(INode<TKeyType, TValueType> root) {
    int size = 0;

    // a complete subtree must have the following attributes
    // 1. All leaves must be within 1 of each other.
    // 2. All leaves must be as far left as possible, i.e, L(child).count() > R(child).count()
    // 3. A complete subtree may have only one node (L child) or two nodes (L, R).

    if (root == null)
    {
        return new TreeInfo<>(true, 0);
    }
    else if (!root.hasLeftChild() && !root.hasRightChild())
    {
        return new TreeInfo<>(true, 1);
    }

    // have children
    TreeInfo<TKeyType, TValueType> leftInfo = calculateLargestCompleteSubtree(root.getLeft());
    TreeInfo<TKeyType, TValueType> rightInfo = calculateLargestCompleteSubtree(root.getRight());

    // case 1: not a complete tree.
    if (!leftInfo.isComplete || !rightInfo.isComplete)
    {
        // Only one subtree is complete. Set it as the max and return false.
        if(leftInfo.isComplete) {
            max = Math.max(max, leftInfo.size);
        }
        else if(rightInfo.isComplete)
        {
            max = Math.max(max, rightInfo.size);
        }

        return new TreeInfo<>(false, -1);
    }

    // case 2: both subtrees complete
    int delta = Math.abs(leftInfo.size - rightInfo.size);
    if (delta <= 1)
    {
        // both are complete but R could be 1 greater...use L tree.
        size = leftInfo.size + 1;
        max = Math.max(max, size);
        return new TreeInfo<>(true, size);
    }
    else
    {
        // limit to size of R + 1 if L - R > 1, otherwise L
        if(leftInfo.size > rightInfo.size)
        {
            max = Math.max(max, leftInfo.size);
            size = rightInfo.size + 1;
        }
        else
        {
            max = Math.max(max, rightInfo.size);
            size = leftInfo.size;
        }

        return new TreeInfo<>(true, size + 1);
    }
}


问:
Consumer/producer locking GUI thread
I made a sample Consumer/Producer thread application, so I can learn how to properly use it.

I want it to allow for one thread to send commands to the GUI thread, to update the GUI with content.

I have it working, but there's one small issue. The GUI thread is my consumer thread, so I have it always checking for new commands (using a while loop). The issue is that because of this while loop, the GUI never displays because it's always stuck in the while loop. Note that the string Queue will eventually be replaced with a more complex object (one that holds data & command type).

I'm not sure how else to allow the GUI thread to consume commands without interrupting GUI functionality. Am I doing something wrong?

Here's my Form1.cs code (the form only contains 1 RichTextBox for showing output called OutputBox).

```<code>using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace MultiThreading
{
   class ThreadCommandQueue
   {
      public static ThreadCommandQueue instance = new ThreadCommandQueue();

      private Queue<string> m_queue;
      private Object m_lock;

      public static ThreadCommandQueue GetInstance()
      {
         return instance;
      }

      private ThreadCommandQueue()
      {
         m_queue = new Queue<string>();
         m_lock = new Object();
      }

      public void Add(
         string data_to_add)
      {
         lock (m_lock)
         {
            m_queue.Enqueue(data_to_add);
         }
      }

      public string Get()
      {
         lock (m_lock)
         {
            if (m_queue.Count > 0)
            {
               return m_queue.Dequeue();
            }

            return null;
         }
      }
   }

   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private void PopulateThreadCommandQueue()
      {
         int i = 0;
         while(true)
         {
            ThreadCommandQueue.GetInstance().Add("Item #: " + i.ToString());
            i++;
         }
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         // Create the Command Queue....
         ThreadCommandQueue.GetInstance();

         // Create a Testing Producer Thread
         Thread ProducerThread = new Thread(PopulateThreadCommandQueue);
         ProducerThread.Start();

         // The GUI thread is the Consumer, so keep checking the CommandQueue for data...
         while(true)
         {
            string latest = ThreadCommandQueue.GetInstance().Get();
            if(latest != null)
            {
               OutputBox.Text += latest + "\n";
            }
         }
      }
   }
}
</code>```

答:
Use ConcurrentQueue. So no locking is required to add and get from Queue.

Also you in real time you will not receive commands continuously from UI thread (while loop). If you have such scenario use a separate thread to receive outcome.

Then from the receivers thread you can update UI using Invoke command, as below.

```<code>//This method called from receiver thread
public void UpdateForm(Data d)
{
   if(this.InvokeRequired)
   {
      this.Invoke(new MethodInvoker(() => this.UpdateFormUI(r)));
   }
   else
   {
      this.UpdateFormUI(data)
   }
}

public void UpdateFormUI(Data d)
{
   //Does actual ui update
}
</code>```

Title: Consumer/producer locking GUI thread

Body:
I made a sample Consumer/Producer thread application, so I can learn how to properly use it.

I want it to allow for one thread to send commands to the GUI thread, to update the GUI with content.

I have it working, but there's one small issue. The GUI thread is my consumer thread, so I have it always checking for new commands (using a while loop). The issue is that because of this while loop, the GUI never displays because it's always stuck in the while loop. Note that the string Queue will eventually be replaced with a more complex object (one that holds data & command type).

I'm not sure how else to allow the GUI thread to consume commands without interrupting GUI functionality. Am I doing something wrong?

Here's my Form1.cs code (the form only contains 1 RichTextBox for showing output called OutputBox).

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace MultiThreading
{
   class ThreadCommandQueue
   {
      public static ThreadCommandQueue instance = new ThreadCommandQueue();

      private Queue<string> m_queue;
      private Object m_lock;

      public static ThreadCommandQueue GetInstance()
      {
         return instance;
      }

      private ThreadCommandQueue()
      {
         m_queue = new Queue<string>();
         m_lock = new Object();
      }

      public void Add(
         string data_to_add)
      {
         lock (m_lock)
         {
            m_queue.Enqueue(data_to_add);
         }
      }

      public string Get()
      {
         lock (m_lock)
         {
            if (m_queue.Count > 0)
            {
               return m_queue.Dequeue();
            }

            return null;
         }
      }
   }

   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private void PopulateThreadCommandQueue()
      {
         int i = 0;
         while(true)
         {
            ThreadCommandQueue.GetInstance().Add("Item #: " + i.ToString());
            i++;
         }
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         // Create the Command Queue....
         ThreadCommandQueue.GetInstance();

         // Create a Testing Producer Thread
         Thread ProducerThread = new Thread(PopulateThreadCommandQueue);
         ProducerThread.Start();

         // The GUI thread is the Consumer, so keep checking the CommandQueue for data...
         while(true)
         {
            string latest = ThreadCommandQueue.GetInstance().Get();
            if(latest != null)
            {
               OutputBox.Text += latest + "\n";
            }
         }
      }
   }
}

Body:
Use ConcurrentQueue. So no locking is required to add and get from Queue.

Also you in real time you will not receive commands continuously from UI thread (while loop). If you have such scenario use a separate thread to receive outcome.

Then from the receivers thread you can update UI using Invoke command, as below.

//This method called from receiver thread
public void UpdateForm(Data d)
{
   if(this.InvokeRequired)
   {
      this.Invoke(new MethodInvoker(() => this.UpdateFormUI(r)));
   }
   else
   {
      this.UpdateFormUI(data)
   }
}

public void UpdateFormUI(Data d)
{
   //Does actual ui update
}


问:
VSTS Node API - can't use the Identities API
I'm having some trouble with the VSTS Node Api - specifically, the Identities API.

I've already successfully used the Git API to perform actions like retrieving a list of repositories:

```<code>// From ./functions/functions.js
module.exports.getRepos = async function (vstsWebApi) {
  var gitApi = vstsWebApi.getGitApi();
  var repos = await gitApi.getRepositories();
  return repos;
}
</code>```

Then, elsewhere, the following works as expected and the object representing the Git repositories is logged to the console:

```<code>let funcs = require("./functions/functions.js");
let vsts = require("vso-node-api");
let accessTokenPromise = VSS.getAccessToken();

accessTokenPromise.then(token => {
  let bearerHandler = vsts.getBearerHandler(token.token);
  let collectionUri = VSS.getWebContext().collection.uri;
  let connect = new vsts.WebApi(collectionUri, bearerHandler);
  let apiCallPromise = funcs.getRepos(connect);
  apiCallPromise.then(
    result => {
      console.log(result);
    }
  )
})
</code>```

However, if I try to do something similar and use the Identities API to listGroups:

```<code>module.exports.getGroups = async function (vstsWebApi) {
  var identitiesApi = vstsWebApi.getIdentitiesApi();
  var groups = await identitiesApi.listGroups();
  return groups;
}
</code>```

Changing the promise to getGroups instead of getRepos...

```<code>...
let apiCallPromise= funcs.getGroups(connect);
apiCallPromise.then(
  result => {
    console.log(result);
  }
...
</code>```

...I get this error:

```<code>Error: Failed to find api location for area: IMS id: 5966283b-4196-4d57-9211-1b68f41ec1c2
</code>```

I'm trying this on my personal VSTS account, so I should be the owner/Administrator - and I'd expect a different error if my access was denied via a permissions issue. I've tried different values for the collectionUri, like including the project name (my-account.visualstudio.com/ProjectABC) but that doesn't work either. I've also tried other Identities API calls, such as getSelf, with the same result.

答: I submit a feedback here: Identities API in VSTS-Node-API preview version, you can vote and follow it.</p>

Body:
I'm having some trouble with the VSTS Node Api - specifically, the Identities API.

I've already successfully used the Git API to perform actions like retrieving a list of repositories:

// From ./functions/functions.js
module.exports.getRepos = async function (vstsWebApi) {
  var gitApi = vstsWebApi.getGitApi();
  var repos = await gitApi.getRepositories();
  return repos;
}

Then, elsewhere, the following works as expected and the object representing the Git repositories is logged to the console:

let funcs = require("./functions/functions.js");
let vsts = require("vso-node-api");
let accessTokenPromise = VSS.getAccessToken();

accessTokenPromise.then(token => {
  let bearerHandler = vsts.getBearerHandler(token.token);
  let collectionUri = VSS.getWebContext().collection.uri;
  let connect = new vsts.WebApi(collectionUri, bearerHandler);
  let apiCallPromise = funcs.getRepos(connect);
  apiCallPromise.then(
    result => {
      console.log(result);
    }
  )
})

However, if I try to do something similar and use the Identities API to listGroups:

module.exports.getGroups = async function (vstsWebApi) {
  var identitiesApi = vstsWebApi.getIdentitiesApi();
  var groups = await identitiesApi.listGroups();
  return groups;
}

Changing the promise to getGroups instead of getRepos...

...
let apiCallPromise= funcs.getGroups(connect);
apiCallPromise.then(
  result => {
    console.log(result);
  }
...

...I get this error:

Error: Failed to find api location for area: IMS id: 5966283b-4196-4d57-9211-1b68f41ec1c2

I'm trying this on my personal VSTS account, so I should be the owner/Administrator - and I'd expect a different error if my access was denied via a permissions issue. I've tried different values for the collectionUri, like including the project name (my-account.visualstudio.com/ProjectABC) but that doesn't work either. I've also tried other Identities API calls, such as getSelf, with the same result.


问:
Get HTML code from dynamic page
I am trying to get the HTML code of the following website.
http://fortune.com/fortune500/list/

But the problem is when we visit this website in browser, it only shows the first 20 companies and when we go to the bottom part of website it loads the next 50 companies.

How do i get the first 700 companies in HTML code from this website?
I tried the code from this website https://www.mkyong.com/java/how-to-get-url-content-in-java/ to get the HTML content but as expected it gives only the top 20 companies

Any help is much appreciated
Thanks

答: You should use Selenium for this. Here is a tutorial on how to use it with StormCrawler. You could also use it directly if you wanted to.</p>

Title: Get HTML code from dynamic page


问:
First Java program (calculator) problems
I'm in the process of learning Java and my first project is a calculator, however I've run into a snag.  I'm trying to get my calculator to let me enter a number then click an operator (+, -, x, /), enter another number then hit an operator again and have the display update and be able to keep this going.

Example, I would like to be able to hit the following and have it display the total each time I hit an operator after the first:

a + b / c - d =

The code I have seems (to me) like it should work but it doesn't.  What am I doing wrong?

The following is the code I'm using when you hit an operator.  By default wait is set to false.  After running through the class once, value1 is stored and wait is set to true and that works fine.  From there it doesn't seem to work quite right:

```<code>class OperatorListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        String input = event.getActionCommand();

        // Set display as string
        String s = display.getText();

        if (!wait) {
            // Convert first input string to double
            try {
                value1 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            dec = false;
        } else {
            // Convert second input string to double
            try {
                value2 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            // Determine operation to be performed
            if (operator == "add") {
                value1 = Operators.add(value1, value2);
            } else if (operator == "subtract") {
                value1 = Operators.subtract(value1, value2);
            } else if (operator == "multiply") {
                value1 = Operators.multiply(value1, value2);
            } else if (operator == "divide") {
                value1 = Operators.divide(value1, value2);
            }

            // Convert final value to string and display
            display.setText(Double.toString(value1));

            dec = false;
        }

        // Determine operator hit
        if (input.equals("+")) {
            operator = "add";
        } else if (input.equals("-")) {
            operator = "subtract";
        } else if (input.equals("x")) {
            operator = "multiply";
        } else if (input.equals("/")) {
            operator = "divide";
        }

        // Set wait
        wait = true;

    }
}
</code>```

EDIT: Updated code to fix some confusion and update the if statement.  Even after this the same problem still exists.  Also, the full source is available here

答:
After searching high and low I finally determined that the problem didn't lie within the code I provided.  I had had a "wait = false;" in my NumberListener class that was screwing up the execution.  To solve this I created 2 separate wait variables and all is working fine so far.

Thanks for the help and the tips guys, +1 to all of you for trying.

OwnerDisplayName: PHLAK

ContentLicense: CC BY-SA 2.5

Body:
I'm in the process of learning Java and my first project is a calculator, however I've run into a snag.  I'm trying to get my calculator to let me enter a number then click an operator (+, -, x, /), enter another number then hit an operator again and have the display update and be able to keep this going.

Example, I would like to be able to hit the following and have it display the total each time I hit an operator after the first:

a + b / c - d =

The code I have seems (to me) like it should work but it doesn't.  What am I doing wrong?

The following is the code I'm using when you hit an operator.  By default wait is set to false.  After running through the class once, value1 is stored and wait is set to true and that works fine.  From there it doesn't seem to work quite right:

class OperatorListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        String input = event.getActionCommand();

        // Set display as string
        String s = display.getText();

        if (!wait) {
            // Convert first input string to double
            try {
                value1 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            dec = false;
        } else {
            // Convert second input string to double
            try {
                value2 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            // Determine operation to be performed
            if (operator == "add") {
                value1 = Operators.add(value1, value2);
            } else if (operator == "subtract") {
                value1 = Operators.subtract(value1, value2);
            } else if (operator == "multiply") {
                value1 = Operators.multiply(value1, value2);
            } else if (operator == "divide") {
                value1 = Operators.divide(value1, value2);
            }

            // Convert final value to string and display
            display.setText(Double.toString(value1));

            dec = false;
        }

        // Determine operator hit
        if (input.equals("+")) {
            operator = "add";
        } else if (input.equals("-")) {
            operator = "subtract";
        } else if (input.equals("x")) {
            operator = "multiply";
        } else if (input.equals("/")) {
            operator = "divide";
        }

        // Set wait
        wait = true;

    }
}

EDIT: Updated code to fix some confusion and update the if statement.  Even after this the same problem still exists.  Also, the full source is available here

LastEditorDisplayName: PHLAK


问:
How do I delay page display until JS is done?
I've done the prerequisite searching of stackoverflow and looking on the internet. I suspect that the answer is ' This can't be done. ' but I'm hoping someone here might have a solution.

My page loads fine, but many of my YUI components don't fully load before being displayed. For example, my DataTable will resize itself when displaying or my buttons will appear in their native form and then get YUI-fied.

Is there a way to delay the displaying of the page until all the Javascript is finished (i.e. all my YUI components are finished rendering)? I don't know how this would happen, as a lot of the JS depends on the DOM being present to manipulate it.

答:
Is there a way to delay the displaying
  of the page

If I understand correctly you would like to hide it until it's done?
If that's the case I have an idea:

add a wrapper around the element you
want to hide (or use
position:absolute to cover it)

give that div a background which use
the color of the surrounding with a
positive z-index

when all your javascript has loaded remove the
z-index or change the color of the background to transparent

Your javascript code would look like this:

do 1. and 2.

load your js

do 3.

Of course it needs to be synchrone.

As an alternative you could use visibility:hidden / visible on the element itself but I dunno for sure if it's well supported.


问:
How Upload large files to Onedrive using PHP-Curl
I need to upload file size grater than 4MB to onedrive account. I am trying with PHP and curl for this. Is anyone tried for this option, Please help me out to solve this issue.</p>

答:
Your application needs to:

Create an upload session

Upload bytes to the upload session

Refer to the OneDrive Dev Center's Upload large files with an upload session documentation page here: https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession#create-an-upload-session for details as to the type of requests to make for each step and what JSON or http response codes to expect.

From a PHP functionality standpoint, you'd want to:

determine the attributes of the file for your upload (file size, file name)

Send post data via curl to create upload session (See section entitled SEND POST FROM CURL in this blog post for an example code snippet for #1.)

parse the uploadUrl from the JSON response to above into a php variable

Send the binary contents via cURL to the uploadURL extracted above (See section entitled Send the binary contents via cURL in this blog post (either send whole file, or in partial chunks- size of file and connection/bandwidth should be taken into consideration to determine approach)

parse the response header (http response code) and conditionally:

retry with expected byte range if it failed (response code of HTTP 416 Requested Range Not Satisfiable)

continue with next byte range if transmitting byte ranges/partials (response code of 202 Accepted) - refer to "Resuming an in-progress upload"

complete/return/exit out of functionality (response code of HTTP 200 OK or HTTP 201 Created)

on any 50x responses, send a GET request (refer to "Resuming an in-progress upload") to determine what to send next/how to resume

In the case of a filename conflict being detected (response code of HTTP/1.1 409 Conflict):

Send a DELETE request using curl command to cancel the upload session (you should get a response code of HTTP/1.1 204 No Content.

Resolve/handle the name conflict

Restart the process


问:
Getting Error "cannot read property split of null"
I have written a script on change event of image uploading and getting it's value then passing it through ajax datatype in json format on click of a button.
But the error is occurring at  this below line

```<code>byteData = byteData.split(';')[1].replace("base64,", "");
</code>```

error message "cannot read property split of null". So exactly what is the issue is occurring

HTML code

```<code><input type='file' id='flImage' name='flImage' />
</code>```

Script

```<code><script type="text/javascript" src="http://cdn.jsdelivr.net/json2/0.1/json2.js"></script>
    <script type="text/javascript">
            $(function () {
                var reader = new FileReader();
                var fileName;
                var contentType;
                $("#flImage").change(function () {
                    if (typeof (FileReader) != "undefined") {
                        var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
                        $($(this)[0].files).each(function () {
                            var file = $(this);
                            if (regex.test(file[0].name.toLowerCase())) {
                                fileName = file[0].name;
                                contentType = file[0].type;
                                reader.readAsDataURL(file[0]);
                            } else {
                                alert(file[0].name + " is not a valid image file.");
                                return false;
                            }
                        });
                    } else {
                        alert("This browser does not support HTML5 FileReader.");
                    }
                });
 $(document).on("click", "[id*=btnFrmSubmit]", function () {
            alert("hi");
            var user = {};
            user.PRODUCT_ID = 1;
 user.TDC_NO = $("[id*=Tdc_No]").val();
user.REVISION = $("#Revision").text();
            user.REVISION_DATE = $("[id*=Revision_Date]").text();
            user.P_GROUP = $("[id*=P_Group]").val();
            user.PROD_DESC = $("[id*=Prod_Desc]").val();
            user.N_I_PRD_STD = $("[id*=N_I_Prd_Std]").val();
            user.APPLN = $("[id*=Appln]").val();
            user.FRM_SUPP = $("[id*=Frm_Supp]").val();
            user.CREATED_DATE = $("#Revision_Date").text();
            user.CREATED_BY = $("[id*=lblUserName]").text();
            var byteData = reader.result;
            byteData = byteData.split(';')[1].replace("base64,", "");
 $.ajax({
                type: "POST",
                url: "TDC.aspx/SaveFrmDetails",
 data: '{user: "' + JSON.stringify(user) + '",byteData: "' + byteData + '", imageName: "' + fileName + '", contentType: "' + contentType + '" }',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
 success: function (response) {
                    alert("User has been added successfully.");
                    window.location.reload();
                }
            });
            return false;
        });
    });
</script>
</code>```

答:
try to check your value for "null" and "undefined" first, before use it : </p>

```<code>if(byteData)
    byteData = byteData.split(';')[1].replace("base64,", "");
</code>```

Body:
I have written a script on change event of image uploading and getting it's value then passing it through ajax datatype in json format on click of a button.
But the error is occurring at  this below line

byteData = byteData.split(';')[1].replace("base64,", "");

error message "cannot read property split of null". So exactly what is the issue is occurring

HTML code

<input type='file' id='flImage' name='flImage' />

Script

Body:
try to check your value for "null" and "undefined" first, before use it :

if(byteData)
    byteData = byteData.split(';')[1].replace("base64,", "");


问:
sed or awk command to merge two line into a single line
I have a text file with the following format.

12345

abcdefg

I need this to be in the same line. So the output should look like this...

12345 abcdefg

How should i proceed ? using sed or awk ?

答:
For given input and expected output below one should work

Using xargs

```<code>$ cat infile
12345
abcdefg

$ xargs < infile
12345 abcdefg
</code>```

Using tr

```<code>$ tr -s '\n' ' ' <infile ; echo
12345 abcdefg
</code>```

Body:
For given input and expected output below one should work

Using xargs

$ cat infile
12345
abcdefg

$ xargs < infile
12345 abcdefg

Using tr

$ tr -s '\n' ' ' <infile ; echo
12345 abcdefg


问:
I want to create an adaptive card with buttons for email and call functionality. Whats the possible way for that?
I want to create an adaptive card with buttons for email and call functionality. I cannot find a format for call and email in adaptive cards. Is there a way to combine adaptive cards with hero cards, since hero cards have the cardAction object functionality ? </p>

答:
Is there a way to combine adaptive cards with hero cards, since hero cards have the cardAction object functionality ?

No, but Buttons within AdaptiveCard are not created using CardAction objects, you can use schema that is defined in AdaptiveCard instead.

There're three kinds of actions OpenUrl, Submit and ShowCard. Here Submit is what we need.

If you want to create AdaptiveCard in C#, you can for example create it and send the message like this:

AdaptiveCard card = new AdaptiveCard()
{
    Body = new List<CardElement>()
    {
        new Container()
        {
            Speak = "<s>Hello!</s><s>Send Email!</s>",
            Items = new List<CardElement>()
            {
                new TextBlock()
                {
                     Text = "Hello!",
                     Weight = TextWeight.Bolder,
                     IsSubtle = true
                },
                new TextBlock()
                {
                     Text = "Send Email!",
                     Wrap = true
                },
                new TextInput()
                {
                    Id = "EmailAddTo",
                    Placeholder = "To:"
                },
                new TextInput()
                {
                    Id = "EmailAddFrom",
                    Placeholder = "From:"
                },
                new TextInput()
                {
                    Id = "Subject",
                    Placeholder = "Subject:"
                },
                new TextInput()
                {
                    Id = "Content",
                    Placeholder = "Content:",
                    IsMultiline = true,
                }
            }
        }
    },
    Actions = new List<ActionBase>()
    {
        new SubmitAction()
        {
            Title = "Send Email",
            DataJson = "{\"Type\": \"EmailSend\"}"
        }
    }
};

Attachment attachment = new Attachment()
{
    ContentType = AdaptiveCard.ContentType,
    Content = card
};

var reply = context.MakeMessage();
reply.Attachments.Add(attachment);

await context.PostAsync(reply,CancellationToken.None);
```

<p>When using <code>Submit</code> action, the Bot Framework will handle the submission and your bot will receive a new <code>IMessageActivity</code> with its <code>Value</code>, you can then handle it in your code for example like this:</p>

<pre class="lang-cs prettyprint-override"><code>private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
    var message = await result;

    if (message.Value != null)
    {
        // Got an Action Submit
        dynamic value = message.Value;
        string submitType = value.Type.ToString();
        switch (submitType)
        {
            case "EmailSend":
                /* */
                return;
        }
    }
}
</code>```

For more information, you can refer to the official Adaptive Cards Bot Sample.

Body:
Is there a way to combine adaptive cards with hero cards, since hero cards have the cardAction object functionality ?

No, but Buttons within AdaptiveCard are not created using CardAction objects, you can use schema that is defined in AdaptiveCard instead.

There're three kinds of actions OpenUrl, Submit and ShowCard. Here Submit is what we need.

If you want to create AdaptiveCard in C#, you can for example create it and send the message like this:

AdaptiveCard card = new AdaptiveCard()
{
    Body = new List<CardElement>()
    {
        new Container()
        {
            Speak = "<s>Hello!</s><s>Send Email!</s>",
            Items = new List<CardElement>()
            {
                new TextBlock()
                {
                     Text = "Hello!",
                     Weight = TextWeight.Bolder,
                     IsSubtle = true
                },
                new TextBlock()
                {
                     Text = "Send Email!",
                     Wrap = true
                },
                new TextInput()
                {
                    Id = "EmailAddTo",
                    Placeholder = "To:"
                },
                new TextInput()
                {
                    Id = "EmailAddFrom",
                    Placeholder = "From:"
                },
                new TextInput()
                {
                    Id = "Subject",
                    Placeholder = "Subject:"
                },
                new TextInput()
                {
                    Id = "Content",
                    Placeholder = "Content:",
                    IsMultiline = true,
                }
            }
        }
    },
    Actions = new List<ActionBase>()
    {
        new SubmitAction()
        {
            Title = "Send Email",
            DataJson = "{\"Type\": \"EmailSend\"}"
        }
    }
};

Attachment attachment = new Attachment()
{
    ContentType = AdaptiveCard.ContentType,
    Content = card
};

var reply = context.MakeMessage();
reply.Attachments.Add(attachment);

await context.PostAsync(reply,CancellationToken.None);

When using Submit action, the Bot Framework will handle the submission and your bot will receive a new IMessageActivity with its Value, you can then handle it in your code for example like this:

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
    var message = await result;

    if (message.Value != null)
    {
        // Got an Action Submit
        dynamic value = message.Value;
        string submitType = value.Type.ToString();
        switch (submitType)
        {
            case "EmailSend":
                /* */
                return;
        }
    }
}

For more information, you can refer to the official Adaptive Cards Bot Sample.


问:
How to call different Function under module.exports
I have a Helper.js file. Under this file mentioned the Code for doing stuff with Database.

```<code>Helper.js FILE
module.exports.test1 = function(req, res){
    ABC.find({}).exec(function(err, post) {
        if(post.length == '0'){
            res.send({'No Data'});
        }else if(err){
            res.send({'Error'});
        }else {
            res.send({'data':post});
        }
    });
}

module.exports.test2 = function(req, res){
    ABC.find({}).exec(function(err, post) {
        if(post.length == '0'){
            res.send({'No Data'});
        }else if(err){
            res.send({'Error'});
        }else {
            res.send({'data':post});
        }
    });
}
</code>```

Now In My getter.js File I am calling the function Like this And it Works Perfectly fine For me i.e Code Like this

```<code>Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1);
router.get('/gettest2', helper.test2);
</code>```

Now my Question is How to Create functions under Single Module.exports???
I also researched and tried this Kind of Code but getting Error i.e "Route.get() requires callback functions but got an [object Undefined]
    at Route.(anonymous function) [as get]"
My Modified Code of Helper.js File is

```<code>Helper.js FILE
    module.exports = {
    test1 = function(req, res){
        ABC.find({}).exec(function(err, post) {
            if(post.length == '0'){
                res.send({'No Data'});
            }else if(err){
                res.send({'Error'});
            }else {
                res.send({'data':post});
            }
        });
    },
    test2 = function(req, res){
        ABC.find({}).exec(function(err, post) {
            if(post.length == '0'){
                res.send({'No Data'});
            }else if(err){
                res.send({'Error'});
            }else {
                res.send({'data':post});
            }
        });
    }
    };
</code>```

And In my getter.js file Code like this

```<code>Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1());
router.get('/gettest2', helper.test2());
</code>```

Please Share the best approach for doing this kind of stuff

答:
It's Done. Main Problem is On getter.js File Calling Wrong Format i.e

Not This Way

```<code>Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1());
router.get('/gettest2', helper.test2());
</code>```

Correct Way is

```<code>Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1);//As it is an object not function
router.get('/gettest2', helper.test2);//As it is an object not function
</code>```

Body:
I have a Helper.js file. Under this file mentioned the Code for doing stuff with Database.

Helper.js FILE
module.exports.test1 = function(req, res){
    ABC.find({}).exec(function(err, post) {
        if(post.length == '0'){
            res.send({'No Data'});
        }else if(err){
            res.send({'Error'});
        }else {
            res.send({'data':post});
        }
    });
}

module.exports.test2 = function(req, res){
    ABC.find({}).exec(function(err, post) {
        if(post.length == '0'){
            res.send({'No Data'});
        }else if(err){
            res.send({'Error'});
        }else {
            res.send({'data':post});
        }
    });
}

Now In My getter.js File I am calling the function Like this And it Works Perfectly fine For me i.e Code Like this

Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1);
router.get('/gettest2', helper.test2);

Now my Question is How to Create functions under Single Module.exports???
I also researched and tried this Kind of Code but getting Error i.e "Route.get() requires callback functions but got an [object Undefined]
    at Route.(anonymous function) [as get]"
My Modified Code of Helper.js File is

Helper.js FILE
    module.exports = {
    test1 = function(req, res){
        ABC.find({}).exec(function(err, post) {
            if(post.length == '0'){
                res.send({'No Data'});
            }else if(err){
                res.send({'Error'});
            }else {
                res.send({'data':post});
            }
        });
    },
    test2 = function(req, res){
        ABC.find({}).exec(function(err, post) {
            if(post.length == '0'){
                res.send({'No Data'});
            }else if(err){
                res.send({'Error'});
            }else {
                res.send({'data':post});
            }
        });
    }
    };

And In my getter.js file Code like this

Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1());
router.get('/gettest2', helper.test2());

Please Share the best approach for doing this kind of stuff

Body:
It's Done. Main Problem is On getter.js File Calling Wrong Format i.e

Not This Way

Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1());
router.get('/gettest2', helper.test2());

Correct Way is

Getter.js FILE
var helper = require('./helper');
router.get('/gettest1', helper.test1);//As it is an object not function
router.get('/gettest2', helper.test2);//As it is an object not function


问:
Validation expression in asp.net
How to disallow use of double quotes " in a textbox

答: use RegularExpressionValidator and set the ValidationExpression='^[^\"]*$', that will allow anything, including empty, other than "

Title: Validation expression in asp.net