2013-07-09 52 views
2

我從SQLite數據庫加載列表時,我的頁面加載,有時在加載時我得到NullReferenceException與錯誤說Object reference not set to an instance of an object.的NullReferenceException當頁面加載

它打破這個代碼在SQLite的類文件

public TableMapping GetMapping (Type type) 
{ 
    if (_mappings == null) { 
     _mappings = new Dictionary<string, TableMapping>(); 
    } 
    TableMapping map; 
    if (!_mappings.TryGetValue (type.FullName, out map)) { 
     map = new TableMapping (type); 
     _mappings [type.FullName] = map; //null here 
    } 
    return map; 
} 

這是我做的,當我的頁面加載

public MainPage() 
{ 
    this.InitializeComponent(); 
    Loaded += MainPage_Loaded; 
} 

void MainPage_Loaded(object sender, RoutedEventArgs e) 
{ 
    createDatabase(); 
    getBowlers(); 
} 

private async void createDatabase() 
{ 
    SQLiteAsyncConnection conn = new SQLiteAsyncConnection(BOWLERS_DATABASE); 
    await conn.CreateTableAsync<Bowler>(); 
    conn = new SQLiteAsyncConnection(GAMES_DATABASE); 
    await conn.CreateTableAsync<Games>(); 
} 

private async void getBowlers() 
{ 
    SQLiteAsyncConnection conn = new SQLiteAsyncConnection(BOWLERS_DATABASE); 

    var query = conn.Table<Bowler>(); 
    itemListView.DataContext = await query.ToListAsync(); 
} 

我是新來的頁面生命週期,但它似乎我試圖從數據庫中儘早提取數據?

編輯

堆棧跟蹤

System.NullReferenceException was unhandled by user code 
HResult=-2147467261 
Message=Object reference not set to an instance of an object. 
Source=mscorlib 
StackTrace: 
    at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) 
    at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value) 
    at SQLite.SQLiteConnection.GetMapping(Type type) in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 231 
    at SQLite.TableQuery`1..ctor(SQLiteConnection conn) in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 2129 
    at SQLite.SQLiteConnection.Table[T]() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 616 
    at SQLite.SQLiteAsyncConnection.Table[T]() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLiteAsync.cs:line 260 
    at Tournament_Director_Windows.MainPage.<getBowlers>d__c.MoveNext() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\MainPage.xaml.cs:line 116 
InnerException: 
+0

哪一行,你才能上的NullReferenceException? –

+0

我在代碼中註釋了它_mappings [type.FullName] = map;' – tyczj

+0

是'_mappings'靜態變量和/或被從多個線程調用? –

回答

4

基於異常,並提供堆棧跟蹤,我認爲你的問題是什麼是描述here

注:

  1. 唯一的例外是從字典代碼所引發的,而不是從你的(用戶)代碼
  2. 唯一的例外是NullReferenceException異常,不ArgumentNullException,所以它不只是一個參數是空

Dictionary不是線程安全的。這意味着如果它被多個線程訪問,則應該對它進行同步。

更新1

好像there is a bug在SQLite的異步處理。

+0

此調用位於外部庫中,因此您需要將調用同步到SQLite庫。 –

+2

我希望我能給你+1兩次,我敢打賭你明白了。對「SQLiteAsyncConnection」的調用不應該在線程間共享。請確保[連接池](http://stackoverflow.com/questions/10703814/sqlite-c-connection-pooling-and-prepared-statement- confusion)已啓用,並且它將爲您共享資源而不共享連接對象。 –

+0

是的,這是一個線程問題,我在'GetMapping'中放了一個'lock',並且從 – tyczj

0

試試這個:

if (!_mappings.ContainsKey(type.FullName)) 
{ 
    _mappings.Add(map); 
} 

_mappings [type.FullName] = map; 
1

原始代碼的問題在於GetMapping方法不是線程安全的。在下面添加一個鎖,強制它是線程安全的並解決問題。基於答案和註釋

,這裏是代碼,改變GetMapping方法在SQLite.cs文件到這個

private Object thisLock = new Object(); // add lock obj 
public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None) 
{ 
    // include original code in the lock block 
    lock (thisLock) 
    { 
     if (_mappings == null) 
     { 
      _mappings = new Dictionary<string, TableMapping>(); 
     } 
     TableMapping map; 
     if (!_mappings.TryGetValue(type.FullName, out map)) 
     { 
      map = new TableMapping(type, createFlags); 
      _mappings[type.FullName] = map; 
     } 
     return map; 
    } 
} 
+0

開始沒有崩潰請說什麼改變了。 –

+0

@JohnSaunders更新 – codingrhythm

+0

好的,但你爲什麼認爲這解決了這個問題? –