Tom Squires
Tom Squires

Reputation: 9286

Instantiate a class in a separate thread without a compile time warning

Is it possible to instantiate a class in a separate thread without a compile time warning?

For example the below code gives the compile time error "Use of unassigned local variable BECheck". I would rather keep AvailabilityCheckBase abstract and not assign it some dummy variable. Creating both BTCheck and BECheck is slow which is why I need it threaded.

    public static AvailabilityCheckBase ByDSL(string dsl)
    {
        AvailabilityCheckBase BECheck;
        AvailabilityCheckBase BTCheck;

        Thread BEThread = new Thread(new ThreadStart(() => BECheck = new BEAvailabilityCheck(dsl)));
        Thread BTThread = new Thread(new ThreadStart(() => BTCheck = new BTAvailabilityCheck(dsl)));

        BEThread.Join();
        BTThread.Join();

        return BECheck.Merge(BTCheck);
    }

Upvotes: 0

Views: 743

Answers (5)

Lazarus
Lazarus

Reputation: 43064

If you assign the values to null you should see the message disappear, this would be good practice. There also doesn't appear to be any checking to make sure that the initialisations worked, you should probably include a check for BECheck and BTCheck still being null at the end of the function before you try to return to avoid an exception being thrown.

Upvotes: 1

penartur
penartur

Reputation: 9912

In order to call BECheck.Merge in your last line, BECheck should be initialized, and the compiler doesn't know it will be created before Thread.Join.

Try writing

    AvailabilityCheckBase BECheck = null;
    AvailabilityCheckBase BTCheck = null;

in the first lines.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1499790

The language has no knowledge of the Thread constructor or the Join method: it can't tell that you will definitely assign values to both variables before Join returns. If you want to keep the current approach, you'll need to assign values to the variables first. I agree this is slightly ugly, but it's the only way of keeping the compiler happy here.

(It's not clear why you're creating two new threads here, given that your original thread is then blocking on both of them, by the way.)

A better approach if you're using .NET 4 would be to use Task<T>, which effectively gives you the "promise" of a value:

Task<AvailabilityCheckBase> beCheck =
    Task.Factory.StartNew(() => new BEAvailabilityCheck(dsl));
Task<AvailabilityCheckBase> btCheck =
    Task.Factory.StartNew(() => new BTAvailabilityCheck(dsl));

return beCheck.Result.Merge(btCheck.Result);

It's worth becoming familiar with Task<T> and the TPL in general, as the new async features in C# 5 are heavily dependent on them.

Upvotes: 4

Pavel Krymets
Pavel Krymets

Reputation: 6293

Use Task's:

 Task<AvailabilityCheckBase> BETask = new Task<AvailabilityCheckBase>(() => BECheck = new BEAvailabilityCheck(dsl));
 Task<AvailabilityCheckBase> BTTask = new Task<AvailabilityCheckBase>(() => BECheck = new BTAvailabilityCheck(dsl));

 BETask.WaitAll(BETask,BTTask);
 AvailabilityCheckBase BECheck = BETask.Result;
 AvailabilityCheckBase BTCheck = BTTask.Result;

Upvotes: 0

AakashM
AakashM

Reputation: 63340

Doesn't this fix your compile error? :

change

    AvailabilityCheckBase BECheck;
    AvailabilityCheckBase BTCheck;

to

    AvailabilityCheckBase BECheck = null;
    AvailabilityCheckBase BTCheck = null;

Upvotes: 3

Related Questions